mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-31 03:27:40 +01:00
parent
1b7f99127d
commit
4ab4bbc23f
@ -245,18 +245,11 @@
|
||||
<file>last.fm/as_disabled.png</file>
|
||||
<file>last.fm/as_light.png</file>
|
||||
<file>last.fm/as.png</file>
|
||||
<file>last.fm/ban.png</file>
|
||||
<file>last.fm/icon_radio.png</file>
|
||||
<file>last.fm/icon_tag.png</file>
|
||||
<file>last.fm/icon_user.png</file>
|
||||
<file>last.fm/lastfm.png</file>
|
||||
<file>last.fm/loved_radio.png</file>
|
||||
<file>last.fm/love.png</file>
|
||||
<file>last.fm/my_friends.png</file>
|
||||
<file>last.fm/my_neighbours.png</file>
|
||||
<file>last.fm/neighbour_radio.png</file>
|
||||
<file>last.fm/personal_radio.png</file>
|
||||
<file>last.fm/recommended_radio.png</file>
|
||||
<file>last.fm/user_purple.png</file>
|
||||
<file>logo.png</file>
|
||||
<file>lumberjacksong.txt</file>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 637 B |
Binary file not shown.
Before Width: | Height: | Size: 580 B |
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
@ -494,6 +494,7 @@ set(HEADERS
|
||||
internet/magnatunesettingspage.h
|
||||
internet/oauthenticator.h
|
||||
internet/savedradio.h
|
||||
internet/scrobbler.h
|
||||
internet/searchboxwidget.h
|
||||
internet/somafmservice.h
|
||||
internet/somafmurlhandler.h
|
||||
@ -817,13 +818,10 @@ optional_source(ENABLE_VISUALISATIONS
|
||||
optional_source(HAVE_LIBLASTFM
|
||||
SOURCES
|
||||
covers/lastfmcoverprovider.cpp
|
||||
globalsearch/lastfmsearchprovider.cpp
|
||||
internet/fixlastfm.cpp
|
||||
internet/lastfmcompat.cpp
|
||||
internet/lastfmservice.cpp
|
||||
internet/lastfmsettingspage.cpp
|
||||
internet/lastfmstationdialog.cpp
|
||||
internet/lastfmurlhandler.cpp
|
||||
songinfo/echonestsimilarartists.cpp
|
||||
songinfo/echonesttags.cpp
|
||||
songinfo/lastfmtrackinfoprovider.cpp
|
||||
@ -832,14 +830,12 @@ optional_source(HAVE_LIBLASTFM
|
||||
covers/lastfmcoverprovider.h
|
||||
internet/lastfmservice.h
|
||||
internet/lastfmsettingspage.h
|
||||
internet/lastfmstationdialog.h
|
||||
songinfo/echonestsimilarartists.h
|
||||
songinfo/echonesttags.h
|
||||
songinfo/lastfmtrackinfoprovider.h
|
||||
songinfo/tagwidget.h
|
||||
UI
|
||||
internet/lastfmsettingspage.ui
|
||||
internet/lastfmstationdialog.ui
|
||||
)
|
||||
|
||||
|
||||
|
@ -39,6 +39,10 @@
|
||||
#include "podcasts/podcastdownloader.h"
|
||||
#include "podcasts/podcastupdater.h"
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
#include "internet/lastfmservice.h"
|
||||
#endif // HAVE_LIBLASTFM
|
||||
|
||||
#ifdef HAVE_MOODBAR
|
||||
#include "moodbar/moodbarcontroller.h"
|
||||
#include "moodbar/moodbarloader.h"
|
||||
@ -69,7 +73,8 @@ Application::Application(QObject* parent)
|
||||
moodbar_loader_(nullptr),
|
||||
moodbar_controller_(nullptr),
|
||||
network_remote_(nullptr),
|
||||
network_remote_helper_(nullptr) {
|
||||
network_remote_helper_(nullptr),
|
||||
scrobbler_(nullptr) {
|
||||
tag_reader_client_ = new TagReaderClient(this);
|
||||
MoveToNewThread(tag_reader_client_);
|
||||
tag_reader_client_->Start();
|
||||
@ -116,6 +121,10 @@ Application::Application(QObject* parent)
|
||||
// crash when a client connects before the manager is initialized!
|
||||
network_remote_helper_ = new NetworkRemoteHelper(this);
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
scrobbler_ = new LastFMService(this, this);
|
||||
#endif // HAVE_LIBLASTFM
|
||||
|
||||
library_->Init();
|
||||
|
||||
DoInAMinuteOrSo(database_, SLOT(DoBackup()));
|
||||
|
@ -44,6 +44,7 @@ class PodcastDownloader;
|
||||
class PlaylistManager;
|
||||
class PodcastBackend;
|
||||
class PodcastUpdater;
|
||||
class Scrobbler;
|
||||
class TagReaderClient;
|
||||
class TaskManager;
|
||||
|
||||
@ -86,6 +87,7 @@ class Application : public QObject {
|
||||
NetworkRemoteHelper* network_remote_helper() const {
|
||||
return network_remote_helper_;
|
||||
}
|
||||
Scrobbler* scrobbler() const { return scrobbler_; }
|
||||
|
||||
LibraryBackend* library_backend() const;
|
||||
LibraryModel* library_model() const;
|
||||
@ -128,6 +130,7 @@ signals:
|
||||
MoodbarController* moodbar_controller_;
|
||||
NetworkRemote* network_remote_;
|
||||
NetworkRemoteHelper* network_remote_helper_;
|
||||
Scrobbler* scrobbler_;
|
||||
|
||||
QList<QObject*> objects_in_threads_;
|
||||
QList<QThread*> threads_;
|
||||
|
@ -76,7 +76,7 @@ void Player::Init() {
|
||||
engine_->SetVolume(settings_.value("volume", 50).toInt());
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
lastfm_ = InternetModel::Service<LastFMService>();
|
||||
lastfm_ = app_->scrobbler();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "playlist/playlistitem.h"
|
||||
|
||||
class Application;
|
||||
class LastFMService;
|
||||
class Scrobbler;
|
||||
|
||||
class PlayerInterface : public QObject {
|
||||
Q_OBJECT
|
||||
@ -173,7 +173,7 @@ class Player : public PlayerInterface {
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
LastFMService* lastfm_;
|
||||
Scrobbler* lastfm_;
|
||||
QSettings settings_;
|
||||
|
||||
PlaylistItemPtr current_item_;
|
||||
|
@ -1,86 +0,0 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "lastfmsearchprovider.h"
|
||||
#include "core/logging.h"
|
||||
#include "internet/lastfmservice.h"
|
||||
|
||||
LastFMSearchProvider::LastFMSearchProvider(LastFMService* service,
|
||||
Application* app, QObject* parent)
|
||||
: SimpleSearchProvider(app, parent), service_(service) {
|
||||
Init("Last.fm", "lastfm", QIcon(":last.fm/as.png"),
|
||||
CanShowConfig | CanGiveSuggestions);
|
||||
icon_ = ScaleAndPad(QImage(":last.fm/as.png"));
|
||||
|
||||
set_safe_words(QStringList() << "lastfm"
|
||||
<< "last.fm");
|
||||
set_max_suggestion_count(3);
|
||||
|
||||
connect(service, SIGNAL(SavedItemsChanged()), SLOT(MaybeRecreateItems()));
|
||||
|
||||
// Load the friends list on startup only if it doesn't involve going to update
|
||||
// info from the server.
|
||||
if (!service_->IsFriendsListStale()) RecreateItems();
|
||||
}
|
||||
|
||||
void LastFMSearchProvider::LoadArtAsync(int id, const Result& result) {
|
||||
// TODO: Maybe we should try to get user pictures for friends?
|
||||
|
||||
emit ArtLoaded(id, icon_);
|
||||
}
|
||||
|
||||
void LastFMSearchProvider::RecreateItems() {
|
||||
QList<Item> items;
|
||||
|
||||
items << Item(tr("My Last.fm Recommended Radio"),
|
||||
QUrl("lastfm://user/USERNAME/recommended"), "recommended");
|
||||
items << Item(tr("My Last.fm Library"),
|
||||
QUrl("lastfm://user/USERNAME/library"), "radio");
|
||||
items << Item(tr("My Last.fm Mix Radio"), QUrl("lastfm://user/USERNAME/mix"),
|
||||
"mix");
|
||||
items << Item(tr("My Last.fm Neighborhood"),
|
||||
QUrl("lastfm://user/USERNAME/neighbours"), "neighborhood");
|
||||
|
||||
const QStringList artists = service_->SavedArtistRadioNames();
|
||||
const QStringList tags = service_->SavedTagRadioNames();
|
||||
const QStringList friends = service_->FriendNames();
|
||||
|
||||
for (const QString& name : artists) {
|
||||
items << Item(tr(LastFMService::kTitleArtist).arg(name),
|
||||
QUrl(QString(LastFMService::kUrlArtist).arg(name)), name);
|
||||
}
|
||||
|
||||
for (const QString& name : tags) {
|
||||
items << Item(tr(LastFMService::kTitleTag).arg(name),
|
||||
QUrl(QString(LastFMService::kUrlTag).arg(name)), name);
|
||||
}
|
||||
|
||||
for (const QString& name : friends) {
|
||||
items << Item(tr("Last.fm Radio Station - %1").arg(name),
|
||||
QUrl("lastfm://user/" + name + "/library"), name);
|
||||
items << Item(tr("Last.fm Mix Radio - %1").arg(name),
|
||||
QUrl("lastfm://user/" + name + "/mix"), name);
|
||||
items << Item(tr("Last.fm Neighbor Radio - %1").arg(name),
|
||||
QUrl("lastfm://user/" + name + "/neighbours"), name);
|
||||
}
|
||||
|
||||
SetItems(items);
|
||||
}
|
||||
|
||||
bool LastFMSearchProvider::IsLoggedIn() { return service_->IsAuthenticated(); }
|
||||
|
||||
void LastFMSearchProvider::ShowConfig() { service_->ShowConfig(); }
|
@ -1,43 +0,0 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LASTFMSEARCHPROVIDER_H
|
||||
#define LASTFMSEARCHPROVIDER_H
|
||||
|
||||
#include "simplesearchprovider.h"
|
||||
|
||||
class LastFMService;
|
||||
|
||||
class LastFMSearchProvider : public SimpleSearchProvider {
|
||||
public:
|
||||
LastFMSearchProvider(LastFMService* service, Application* app,
|
||||
QObject* parent);
|
||||
|
||||
void LoadArtAsync(int id, const Result& result);
|
||||
|
||||
bool IsLoggedIn();
|
||||
void ShowConfig();
|
||||
|
||||
protected:
|
||||
void RecreateItems();
|
||||
|
||||
private:
|
||||
LastFMService* service_;
|
||||
QImage icon_;
|
||||
};
|
||||
|
||||
#endif // LASTFMSEARCHPROVIDER_H
|
@ -38,9 +38,6 @@
|
||||
#include "podcasts/podcastservice.h"
|
||||
#include "smartplaylists/generatormimedata.h"
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
#include "lastfmservice.h"
|
||||
#endif
|
||||
#ifdef HAVE_GOOGLE_DRIVE
|
||||
#include "googledriveservice.h"
|
||||
#endif
|
||||
@ -57,7 +54,7 @@
|
||||
#include "boxservice.h"
|
||||
#endif
|
||||
#ifdef HAVE_VK
|
||||
#include "vkservice.h"
|
||||
#include "vkservice.h"
|
||||
#endif
|
||||
|
||||
using smart_playlists::Generator;
|
||||
@ -80,9 +77,6 @@ InternetModel::InternetModel(Application* app, QObject* parent)
|
||||
AddService(new DigitallyImportedService(app, this));
|
||||
AddService(new IcecastService(app, this));
|
||||
AddService(new JamendoService(app, this));
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
AddService(new LastFMService(app, this));
|
||||
#endif
|
||||
#ifdef HAVE_GOOGLE_DRIVE
|
||||
AddService(new GoogleDriveService(app, this));
|
||||
#endif
|
||||
@ -172,13 +166,13 @@ InternetService* InternetModel::ServiceByName(const QString& name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InternetService* InternetModel::ServiceForItem(const QStandardItem* item)
|
||||
const {
|
||||
InternetService* InternetModel::ServiceForItem(
|
||||
const QStandardItem* item) const {
|
||||
return ServiceForIndex(indexFromItem(item));
|
||||
}
|
||||
|
||||
InternetService* InternetModel::ServiceForIndex(const QModelIndex& index)
|
||||
const {
|
||||
InternetService* InternetModel::ServiceForIndex(
|
||||
const QModelIndex& index) const {
|
||||
QModelIndex current_index = index;
|
||||
while (current_index.isValid()) {
|
||||
InternetService* service =
|
||||
|
@ -43,8 +43,6 @@
|
||||
#endif
|
||||
|
||||
#include "lastfmcompat.h"
|
||||
#include "lastfmstationdialog.h"
|
||||
#include "lastfmurlhandler.h"
|
||||
#include "internetmodel.h"
|
||||
#include "internetplaylistitem.h"
|
||||
#include "core/application.h"
|
||||
@ -55,8 +53,6 @@
|
||||
#include "core/taskmanager.h"
|
||||
#include "covers/coverproviders.h"
|
||||
#include "covers/lastfmcoverprovider.h"
|
||||
#include "globalsearch/globalsearch.h"
|
||||
#include "globalsearch/lastfmsearchprovider.h"
|
||||
#include "ui/iconloader.h"
|
||||
#include "ui/settingsdialog.h"
|
||||
|
||||
@ -73,72 +69,20 @@ const char* LastFMService::kAudioscrobblerClientId = "tng";
|
||||
const char* LastFMService::kApiKey = "75d20fb472be99275392aefa2760ea09";
|
||||
const char* LastFMService::kSecret = "d3072b60ae626be12be69448f5c46e70";
|
||||
|
||||
const char* LastFMService::kUrlArtist = "lastfm://artist/%1/similarartists";
|
||||
const char* LastFMService::kUrlTag = "lastfm://globaltags/%1";
|
||||
const char* LastFMService::kUrlCustom = "lastfm://rql/%1";
|
||||
|
||||
const char* LastFMService::kTitleArtist =
|
||||
QT_TR_NOOP("Last.fm Similar Artists to %1");
|
||||
const char* LastFMService::kTitleTag = QT_TR_NOOP("Last.fm Tag Radio: %1");
|
||||
const char* LastFMService::kTitleCustom =
|
||||
QT_TR_NOOP("Last.fm Custom Radio: %1");
|
||||
|
||||
const int LastFMService::kFriendsCacheDurationSecs = 60 * 60 * 24; // 1 day
|
||||
|
||||
LastFMService::LastFMService(Application* app, InternetModel* parent)
|
||||
: InternetService(kServiceName, app, parent, parent),
|
||||
url_handler_(new LastFMUrlHandler(this, this)),
|
||||
LastFMService::LastFMService(Application* app, QObject* parent)
|
||||
: Scrobbler(parent),
|
||||
scrobbler_(nullptr),
|
||||
already_scrobbled_(false),
|
||||
station_dialog_(new LastFMStationDialog),
|
||||
context_menu_(new QMenu),
|
||||
initial_tune_(false),
|
||||
tune_task_id_(0),
|
||||
scrobbling_enabled_(false),
|
||||
root_item_(nullptr),
|
||||
artist_list_(nullptr),
|
||||
tag_list_(nullptr),
|
||||
custom_list_(nullptr),
|
||||
friends_list_(nullptr),
|
||||
neighbours_list_(nullptr),
|
||||
friend_names_(kSettingsGroup, "friend_names", kFriendsCacheDurationSecs),
|
||||
connection_problems_(false) {
|
||||
connection_problems_(false),
|
||||
app_(app) {
|
||||
ReloadSettings();
|
||||
|
||||
// we emit the signal the first time to be sure the buttons are in the right
|
||||
// state
|
||||
emit ScrobblingEnabledChanged(scrobbling_enabled_);
|
||||
|
||||
context_menu_->addActions(GetPlaylistActions());
|
||||
remove_action_ = context_menu_->addAction(IconLoader::Load("list-remove"),
|
||||
tr("Remove"), this, SLOT(Remove()));
|
||||
context_menu_->addSeparator();
|
||||
add_artist_action_ = context_menu_->addAction(
|
||||
QIcon(":last.fm/icon_radio.png"), tr("Play artist radio..."), this,
|
||||
SLOT(AddArtistRadio()));
|
||||
add_tag_action_ = context_menu_->addAction(QIcon(":last.fm/icon_tag.png"),
|
||||
tr("Play tag radio..."), this,
|
||||
SLOT(AddTagRadio()));
|
||||
add_custom_action_ = context_menu_->addAction(
|
||||
QIcon(":last.fm/icon_radio.png"), tr("Play custom radio..."), this,
|
||||
SLOT(AddCustomRadio()));
|
||||
refresh_friends_action_ = context_menu_->addAction(
|
||||
IconLoader::Load("view-refresh"), tr("Refresh friends list"), this,
|
||||
SLOT(ForceRefreshFriends()));
|
||||
context_menu_->addAction(IconLoader::Load("configure"),
|
||||
tr("Configure Last.fm..."), this,
|
||||
SLOT(ShowConfig()));
|
||||
|
||||
remove_action_->setEnabled(false);
|
||||
add_artist_action_->setEnabled(false);
|
||||
add_tag_action_->setEnabled(false);
|
||||
add_custom_action_->setEnabled(false);
|
||||
|
||||
app_->player()->RegisterUrlHandler(url_handler_);
|
||||
app_->cover_providers()->AddProvider(new LastFmCoverProvider(this));
|
||||
|
||||
app_->global_search()->AddProvider(
|
||||
new LastFMSearchProvider(this, app_, this));
|
||||
}
|
||||
|
||||
LastFMService::~LastFMService() {}
|
||||
@ -154,7 +98,6 @@ void LastFMService::ReloadSettings() {
|
||||
scrobble_button_visible_ =
|
||||
settings.value("ShowScrobbleButton", true).toBool();
|
||||
prefer_albumartist_ = settings.value("PreferAlbumArtist", false).toBool();
|
||||
friend_names_.Load();
|
||||
|
||||
// avoid emitting signal if it's not changed
|
||||
if (scrobbling_enabled_old != scrobbling_enabled_)
|
||||
@ -178,121 +121,6 @@ bool LastFMService::IsSubscriber() const {
|
||||
return settings.value("Subscriber", false).toBool();
|
||||
}
|
||||
|
||||
QStandardItem* LastFMService::CreateRootItem() {
|
||||
root_item_ = new QStandardItem(QIcon(":last.fm/as.png"), kServiceName);
|
||||
root_item_->setData(true, InternetModel::Role_CanLazyLoad);
|
||||
return root_item_;
|
||||
}
|
||||
|
||||
void LastFMService::LazyPopulate(QStandardItem* parent) {
|
||||
switch (parent->data(InternetModel::Role_Type).toInt()) {
|
||||
case InternetModel::Type_Service:
|
||||
// Normal radio types
|
||||
CreateStationItem(parent, tr("My Recommendations"),
|
||||
":last.fm/recommended_radio.png",
|
||||
QUrl("lastfm://user/USERNAME/recommended"),
|
||||
tr("My Last.fm Recommended Radio"));
|
||||
CreateStationItem(
|
||||
parent, tr("My Radio Station"), ":last.fm/personal_radio.png",
|
||||
QUrl("lastfm://user/USERNAME/library"), tr("My Last.fm Library"));
|
||||
CreateStationItem(parent, tr("My Mix Radio"), ":last.fm/loved_radio.png",
|
||||
QUrl("lastfm://user/USERNAME/mix"),
|
||||
tr("My Last.fm Mix Radio"));
|
||||
CreateStationItem(parent, tr("My Neighborhood"),
|
||||
":last.fm/neighbour_radio.png",
|
||||
QUrl("lastfm://user/USERNAME/neighbours"),
|
||||
tr("My Last.fm Neighborhood"));
|
||||
|
||||
// Types that have children
|
||||
artist_list_ = new QStandardItem(QIcon(":last.fm/icon_radio.png"),
|
||||
tr("Artist radio"));
|
||||
artist_list_->setData(Type_Artists, InternetModel::Role_Type);
|
||||
parent->appendRow(artist_list_);
|
||||
|
||||
tag_list_ =
|
||||
new QStandardItem(QIcon(":last.fm/icon_tag.png"), tr("Tag radio"));
|
||||
tag_list_->setData(Type_Tags, InternetModel::Role_Type);
|
||||
parent->appendRow(tag_list_);
|
||||
|
||||
custom_list_ = new QStandardItem(QIcon(":last.fm/icon_radio.png"),
|
||||
tr("Custom radio"));
|
||||
custom_list_->setData(Type_Custom, InternetModel::Role_Type);
|
||||
parent->appendRow(custom_list_);
|
||||
|
||||
RestoreList("artists", kUrlArtist, tr(kTitleArtist),
|
||||
QIcon(":last.fm/icon_radio.png"), artist_list_);
|
||||
RestoreList("tags", kUrlTag, tr(kTitleTag),
|
||||
QIcon(":last.fm/icon_tag.png"), tag_list_);
|
||||
RestoreList("custom", kUrlCustom, tr(kTitleCustom),
|
||||
QIcon(":last.fm/icon_radio.png"), custom_list_);
|
||||
|
||||
friends_list_ =
|
||||
new QStandardItem(QIcon(":last.fm/my_friends.png"), tr("Friends"));
|
||||
friends_list_->setData(Type_Friends, InternetModel::Role_Type);
|
||||
friends_list_->setData(true, InternetModel::Role_CanLazyLoad);
|
||||
parent->appendRow(friends_list_);
|
||||
|
||||
neighbours_list_ = new QStandardItem(QIcon(":last.fm/my_neighbours.png"),
|
||||
tr("Neighbors"));
|
||||
neighbours_list_->setData(Type_Neighbours, InternetModel::Role_Type);
|
||||
neighbours_list_->setData(true, InternetModel::Role_CanLazyLoad);
|
||||
parent->appendRow(neighbours_list_);
|
||||
|
||||
if (!IsAuthenticated()) ShowConfig();
|
||||
|
||||
add_artist_action_->setEnabled(true);
|
||||
add_tag_action_->setEnabled(true);
|
||||
add_custom_action_->setEnabled(true);
|
||||
break;
|
||||
|
||||
case Type_Friends:
|
||||
RefreshFriends(false);
|
||||
break;
|
||||
|
||||
case Type_Neighbours:
|
||||
RefreshNeighbours();
|
||||
break;
|
||||
|
||||
case Type_OtherUser:
|
||||
CreateStationItem(parent,
|
||||
tr("Last.fm Radio Station - %1").arg(parent->text()),
|
||||
":last.fm/personal_radio.png",
|
||||
QUrl("lastfm://user/" + parent->text() + "/library"),
|
||||
tr("Last.fm Library - %1").arg(parent->text()));
|
||||
CreateStationItem(parent,
|
||||
tr("Last.fm Mix Radio - %1").arg(parent->text()),
|
||||
":last.fm/loved_radio.png",
|
||||
QUrl("lastfm://user/" + parent->text() + "/mix"),
|
||||
tr("Last.fm Mix Radio - %1").arg(parent->text()));
|
||||
CreateStationItem(parent,
|
||||
tr("Last.fm Neighbor Radio - %1").arg(parent->text()),
|
||||
":last.fm/neighbour_radio.png",
|
||||
QUrl("lastfm://user/" + parent->text() + "/neighbours"),
|
||||
tr("Last.fm Neighbor Radio - %1").arg(parent->text()));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItem* LastFMService::CreateStationItem(QStandardItem* parent,
|
||||
const QString& name,
|
||||
const QString& icon,
|
||||
const QUrl& url,
|
||||
const QString& title) {
|
||||
Song song;
|
||||
song.set_url(url);
|
||||
song.set_title(title);
|
||||
|
||||
QStandardItem* ret = new QStandardItem(QIcon(icon), name);
|
||||
ret->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata);
|
||||
ret->setData(InternetModel::PlayBehaviour_SingleItem,
|
||||
InternetModel::Role_PlayBehaviour);
|
||||
parent->appendRow(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LastFMService::Authenticate(const QString& username,
|
||||
const QString& password) {
|
||||
QMap<QString, QString> params;
|
||||
@ -311,8 +139,6 @@ void LastFMService::SignOut() {
|
||||
lastfm::ws::Username.clear();
|
||||
lastfm::ws::SessionKey.clear();
|
||||
|
||||
friend_names_.Update(QStringList());
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
|
||||
@ -386,51 +212,6 @@ QUrl LastFMService::FixupUrl(const QUrl& url) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
QUrl LastFMService::DeququeNextMediaUrl() {
|
||||
if (playlist_.empty()) {
|
||||
return QUrl();
|
||||
}
|
||||
|
||||
lastfm::MutableTrack track = playlist_.dequeue();
|
||||
track.stamp();
|
||||
|
||||
already_scrobbled_ = false;
|
||||
last_track_ = track;
|
||||
if (playlist_.empty()) {
|
||||
FetchMoreTracks();
|
||||
}
|
||||
|
||||
next_metadata_ = track;
|
||||
StreamMetadataReady();
|
||||
|
||||
return last_track_.url();
|
||||
}
|
||||
|
||||
void LastFMService::StreamMetadataReady() {
|
||||
Song metadata;
|
||||
metadata.InitFromLastFM(next_metadata_);
|
||||
|
||||
if (art_urls_.contains(next_metadata_))
|
||||
metadata.set_art_automatic(art_urls_[next_metadata_]);
|
||||
|
||||
emit StreamMetadataFound(last_url_, metadata);
|
||||
}
|
||||
|
||||
void LastFMService::TunerError(lastfm::ws::Error error) {
|
||||
qLog(Warning) << "Last.fm error" << error;
|
||||
if (!initial_tune_) return;
|
||||
|
||||
app_->task_manager()->SetTaskFinished(tune_task_id_);
|
||||
tune_task_id_ = 0;
|
||||
|
||||
if (error == lastfm::ws::NotEnoughContent) {
|
||||
url_handler_->TunerError();
|
||||
return;
|
||||
}
|
||||
|
||||
emit StreamError(ErrorString(error));
|
||||
}
|
||||
|
||||
QString LastFMService::ErrorString(lastfm::ws::Error error) const {
|
||||
switch (error) {
|
||||
case lastfm::ws::InvalidService:
|
||||
@ -477,13 +258,6 @@ QString LastFMService::ErrorString(lastfm::ws::Error error) const {
|
||||
}
|
||||
}
|
||||
|
||||
void LastFMService::TunerTrackAvailable() {
|
||||
if (initial_tune_) {
|
||||
url_handler_->TunerTrackAvailable();
|
||||
initial_tune_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool LastFMService::InitScrobbler() {
|
||||
if (!IsAuthenticated() || !IsScrobblingEnabled()) return false;
|
||||
|
||||
@ -610,357 +384,6 @@ void LastFMService::Ban() {
|
||||
app_->player()->Next();
|
||||
}
|
||||
|
||||
void LastFMService::ShowContextMenu(const QPoint& global_pos) {
|
||||
switch (model()
|
||||
->current_index()
|
||||
.parent()
|
||||
.data(InternetModel::Role_Type)
|
||||
.toInt()) {
|
||||
case Type_Artists:
|
||||
case Type_Tags:
|
||||
case Type_Custom:
|
||||
remove_action_->setEnabled(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
remove_action_->setEnabled(false);
|
||||
break;
|
||||
}
|
||||
|
||||
const bool playable = model()->IsPlayable(model()->current_index());
|
||||
GetAppendToPlaylistAction()->setEnabled(playable);
|
||||
GetReplacePlaylistAction()->setEnabled(playable);
|
||||
GetOpenInNewPlaylistAction()->setEnabled(playable);
|
||||
context_menu_->popup(global_pos);
|
||||
}
|
||||
|
||||
QStringList LastFMService::FriendNames() {
|
||||
// Update the list for next time, in the main thread.
|
||||
if (IsFriendsListStale())
|
||||
metaObject()->invokeMethod(this, "RefreshFriends", Qt::QueuedConnection);
|
||||
|
||||
return friend_names_.Data();
|
||||
}
|
||||
|
||||
static QStringList SavedArtistOrTagRadioNames(const QString& name) {
|
||||
QStringList ret;
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(LastFMService::kSettingsGroup);
|
||||
int count = s.beginReadArray(name);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
s.setArrayIndex(i);
|
||||
ret << s.value("key").toString();
|
||||
}
|
||||
s.endArray();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QStringList LastFMService::SavedArtistRadioNames() const {
|
||||
return SavedArtistOrTagRadioNames("artists");
|
||||
}
|
||||
|
||||
QStringList LastFMService::SavedTagRadioNames() const {
|
||||
return SavedArtistOrTagRadioNames("tags");
|
||||
}
|
||||
|
||||
void LastFMService::RefreshFriends() { RefreshFriends(false); }
|
||||
|
||||
void LastFMService::ForceRefreshFriends() { RefreshFriends(true); }
|
||||
|
||||
void LastFMService::RefreshFriends(bool force) {
|
||||
if (!IsAuthenticated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!friends_list_) {
|
||||
root_item_->setData(false, InternetModel::Role_CanLazyLoad);
|
||||
LazyPopulate(root_item_);
|
||||
}
|
||||
|
||||
if (!force && !IsFriendsListStale()) {
|
||||
PopulateFriendsList();
|
||||
return;
|
||||
}
|
||||
|
||||
lastfm::compat::AuthenticatedUser user;
|
||||
QNetworkReply* reply = user.getFriends();
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(RefreshFriendsFinished(QNetworkReply*)), reply);
|
||||
}
|
||||
|
||||
void LastFMService::RefreshNeighbours() {
|
||||
if (!neighbours_list_ || !IsAuthenticated()) return;
|
||||
|
||||
lastfm::compat::AuthenticatedUser user;
|
||||
QNetworkReply* reply = user.getNeighbours();
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(RefreshNeighboursFinished(QNetworkReply*)), reply);
|
||||
}
|
||||
|
||||
void LastFMService::RefreshFriendsFinished(QNetworkReply* reply) {
|
||||
QList<lastfm::User> friends;
|
||||
if (!lastfm::compat::ParseUserList(reply, &friends)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList names;
|
||||
for (const lastfm::User& f : friends) {
|
||||
names << f.name();
|
||||
}
|
||||
|
||||
friend_names_.Update(names);
|
||||
|
||||
PopulateFriendsList();
|
||||
emit SavedItemsChanged();
|
||||
}
|
||||
|
||||
void LastFMService::PopulateFriendsList() {
|
||||
if (friends_list_->hasChildren())
|
||||
friends_list_->removeRows(0, friends_list_->rowCount());
|
||||
|
||||
for (const QString& name : friend_names_) {
|
||||
Song song;
|
||||
song.set_url(QUrl("lastfm://user/" + name + "/library"));
|
||||
song.set_title(tr("Last.fm Library - %1").arg(name));
|
||||
|
||||
QStandardItem* item =
|
||||
new QStandardItem(QIcon(":last.fm/icon_user.png"), name);
|
||||
item->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata);
|
||||
item->setData(true, InternetModel::Role_CanLazyLoad);
|
||||
item->setData(Type_OtherUser, InternetModel::Role_Type);
|
||||
item->setData(InternetModel::PlayBehaviour_SingleItem,
|
||||
InternetModel::Role_PlayBehaviour);
|
||||
friends_list_->appendRow(item);
|
||||
}
|
||||
}
|
||||
|
||||
void LastFMService::RefreshNeighboursFinished(QNetworkReply* reply) {
|
||||
QList<lastfm::User> neighbours;
|
||||
if (!lastfm::compat::ParseUserList(reply, &neighbours)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (neighbours_list_->hasChildren())
|
||||
neighbours_list_->removeRows(0, neighbours_list_->rowCount());
|
||||
|
||||
for (const lastfm::User& n : neighbours) {
|
||||
Song song;
|
||||
song.set_url(QUrl("lastfm://user/" + n.name() + "/library"));
|
||||
song.set_title(tr("Last.fm Library - %1").arg(n.name()));
|
||||
|
||||
QStandardItem* item =
|
||||
new QStandardItem(QIcon(":last.fm/user_purple.png"), n.name());
|
||||
item->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata);
|
||||
item->setData(true, InternetModel::Role_CanLazyLoad);
|
||||
item->setData(Type_OtherUser, InternetModel::Role_Type);
|
||||
item->setData(InternetModel::PlayBehaviour_SingleItem,
|
||||
InternetModel::Role_PlayBehaviour);
|
||||
neighbours_list_->appendRow(item);
|
||||
}
|
||||
}
|
||||
|
||||
void LastFMService::AddArtistRadio() {
|
||||
AddArtistOrTag("artists", LastFMStationDialog::Artist, kUrlArtist,
|
||||
tr(kTitleArtist), ":last.fm/icon_radio.png", artist_list_);
|
||||
}
|
||||
|
||||
void LastFMService::AddTagRadio() {
|
||||
AddArtistOrTag("tags", LastFMStationDialog::Tag, kUrlTag, tr(kTitleTag),
|
||||
":last.fm/icon_tag.png", tag_list_);
|
||||
}
|
||||
|
||||
void LastFMService::AddCustomRadio() {
|
||||
AddArtistOrTag("custom", LastFMStationDialog::Custom, kUrlCustom,
|
||||
tr(kTitleCustom), ":last.fm/icon_radio.png", custom_list_);
|
||||
}
|
||||
|
||||
void LastFMService::AddArtistOrTag(const QString& name,
|
||||
LastFMStationDialog::Type dialog_type,
|
||||
const QString& url_pattern,
|
||||
const QString& title_pattern,
|
||||
const QString& icon, QStandardItem* list) {
|
||||
station_dialog_->SetType(dialog_type);
|
||||
if (station_dialog_->exec() == QDialog::Rejected) return;
|
||||
|
||||
if (station_dialog_->content().isEmpty()) return;
|
||||
|
||||
QString content = station_dialog_->content();
|
||||
QString url;
|
||||
if (name == "custom" && content.startsWith("lastfm://")) {
|
||||
url = content;
|
||||
} else if (name == "custom") {
|
||||
url = url_pattern.arg(QString(content.toUtf8().toBase64()));
|
||||
} else {
|
||||
url = url_pattern.arg(content);
|
||||
}
|
||||
|
||||
Song song;
|
||||
song.set_url(QUrl((url)));
|
||||
song.set_title(title_pattern.arg(content));
|
||||
|
||||
QStandardItem* item = new QStandardItem(QIcon(icon), content);
|
||||
item->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata);
|
||||
item->setData(InternetModel::PlayBehaviour_SingleItem,
|
||||
InternetModel::Role_PlayBehaviour);
|
||||
list->appendRow(item);
|
||||
emit AddItemToPlaylist(item->index(), AddMode_Append);
|
||||
|
||||
SaveList(name, list);
|
||||
|
||||
emit SavedItemsChanged();
|
||||
}
|
||||
|
||||
void LastFMService::SaveList(const QString& name, QStandardItem* list) const {
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
|
||||
settings.beginWriteArray(name, list->rowCount());
|
||||
for (int i = 0; i < list->rowCount(); ++i) {
|
||||
settings.setArrayIndex(i);
|
||||
settings.setValue("key", list->child(i)->text());
|
||||
}
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
void LastFMService::RestoreList(const QString& name, const QString& url_pattern,
|
||||
const QString& title_pattern, const QIcon& icon,
|
||||
QStandardItem* parent) {
|
||||
if (parent->hasChildren()) parent->removeRows(0, parent->rowCount());
|
||||
|
||||
const QStringList keys = SavedArtistOrTagRadioNames(name);
|
||||
|
||||
for (const QString& key : keys) {
|
||||
QString url;
|
||||
if (name == "custom" && key.startsWith("lastfm://")) {
|
||||
url = key;
|
||||
} else if (name == "custom") {
|
||||
url = url_pattern.arg(QString(key.toUtf8().toBase64()));
|
||||
} else {
|
||||
url = url_pattern.arg(key);
|
||||
}
|
||||
|
||||
Song song;
|
||||
song.set_url(QUrl(url));
|
||||
song.set_title(title_pattern.arg(key));
|
||||
|
||||
QStandardItem* item = new QStandardItem(icon, key);
|
||||
item->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata);
|
||||
item->setData(InternetModel::PlayBehaviour_SingleItem,
|
||||
InternetModel::Role_PlayBehaviour);
|
||||
parent->appendRow(item);
|
||||
}
|
||||
}
|
||||
|
||||
void LastFMService::Remove() {
|
||||
QStandardItem* context_item =
|
||||
model()->itemFromIndex(model()->current_index());
|
||||
int type = context_item->parent()->data(InternetModel::Role_Type).toInt();
|
||||
|
||||
context_item->parent()->removeRow(context_item->row());
|
||||
|
||||
if (type == Type_Artists)
|
||||
SaveList("artists", artist_list_);
|
||||
else if (type == Type_Tags)
|
||||
SaveList("tags", tag_list_);
|
||||
else if (type == Type_Custom)
|
||||
SaveList("custom", custom_list_);
|
||||
}
|
||||
|
||||
void LastFMService::FetchMoreTracks() {
|
||||
QMap<QString, QString> params;
|
||||
params["method"] = "radio.getPlaylist";
|
||||
params["rtp"] = "1";
|
||||
QNetworkReply* reply = lastfm::ws::post(params);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(FetchMoreTracksFinished(QNetworkReply*)), reply);
|
||||
}
|
||||
|
||||
void LastFMService::FetchMoreTracksFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
app_->task_manager()->SetTaskFinished(tune_task_id_);
|
||||
tune_task_id_ = 0;
|
||||
|
||||
lastfm::XmlQuery query(lastfm::compat::EmptyXmlQuery());
|
||||
if (lastfm::compat::ParseQuery(reply->readAll(), &query)) {
|
||||
const XmlQuery& playlist = query["playlist"];
|
||||
for (const XmlQuery& q : playlist["trackList"].children("track")) {
|
||||
lastfm::MutableTrack t;
|
||||
t.setUrl(QUrl(q["location"].text()));
|
||||
t.setExtra("trackauth", q["extension"]["trackauth"].text());
|
||||
t.setTitle(q["title"].text());
|
||||
t.setArtist(q["creator"].text());
|
||||
t.setAlbum(q["album"].text());
|
||||
t.setDuration(q["duration"].text().toInt() / 1000);
|
||||
t.setSource(lastfm::Track::LastFmRadio);
|
||||
|
||||
art_urls_[t] = q["image"].text();
|
||||
playlist_ << t;
|
||||
}
|
||||
} else {
|
||||
emit StreamError(tr("Couldn't load the last.fm radio station"));
|
||||
return;
|
||||
}
|
||||
|
||||
TunerTrackAvailable();
|
||||
}
|
||||
|
||||
void LastFMService::Tune(const QUrl& url) {
|
||||
if (!tune_task_id_)
|
||||
tune_task_id_ =
|
||||
app_->task_manager()->StartTask(tr("Loading Last.fm radio"));
|
||||
|
||||
last_url_ = url;
|
||||
initial_tune_ = true;
|
||||
const lastfm::RadioStation station(FixupUrl(url).toString());
|
||||
|
||||
playlist_.clear();
|
||||
|
||||
// Remove all the old album art URLs
|
||||
art_urls_.clear();
|
||||
|
||||
QMap<QString, QString> params;
|
||||
params["method"] = "radio.tune";
|
||||
params["station"] = station.url();
|
||||
QNetworkReply* reply = lastfm::ws::post(params);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(TuneFinished(QNetworkReply*)), reply);
|
||||
}
|
||||
|
||||
void LastFMService::TuneFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
FetchMoreTracks();
|
||||
}
|
||||
|
||||
PlaylistItem::Options LastFMService::playlistitem_options() const {
|
||||
return PlaylistItem::LastFMControls | PlaylistItem::PauseDisabled |
|
||||
PlaylistItem::SeekDisabled;
|
||||
}
|
||||
|
||||
PlaylistItemPtr LastFMService::PlaylistItemForUrl(const QUrl& url) {
|
||||
// This is a bit of a hack, it's only used by the artist/song info tag
|
||||
// widgets for tag radio and similar artists radio.
|
||||
|
||||
if (url.scheme() != "lastfm") return PlaylistItemPtr();
|
||||
|
||||
QStringList sections(url.path().split("/", QString::SkipEmptyParts));
|
||||
|
||||
Song song;
|
||||
song.set_url(url);
|
||||
|
||||
if (sections.count() == 2 && url.host() == "artist" &&
|
||||
sections[1] == "similarartists") {
|
||||
song.set_title(tr(kTitleArtist).arg(sections[0]));
|
||||
} else if (sections.count() == 1 && url.host() == "globaltags") {
|
||||
song.set_title(tr(kTitleTag).arg(sections[0]));
|
||||
} else {
|
||||
return PlaylistItemPtr();
|
||||
}
|
||||
|
||||
return PlaylistItemPtr(new InternetPlaylistItem(this, song));
|
||||
}
|
||||
|
||||
void LastFMService::ToggleScrobbling() {
|
||||
// toggle status
|
||||
scrobbling_enabled_ = !scrobbling_enabled_;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <memory>
|
||||
|
||||
namespace lastfm {
|
||||
class RadioStation;
|
||||
class Track;
|
||||
}
|
||||
|
||||
@ -30,29 +29,19 @@ uint qHash(const lastfm::Track& track);
|
||||
|
||||
#include "lastfmcompat.h"
|
||||
|
||||
#include "internetmodel.h"
|
||||
#include "internetservice.h"
|
||||
#include "lastfmstationdialog.h"
|
||||
#include "core/cachedlist.h"
|
||||
#include "core/song.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QMap>
|
||||
#include <QMenu>
|
||||
#include <QQueue>
|
||||
#include "internet/scrobbler.h"
|
||||
|
||||
class Application;
|
||||
class LastFMUrlHandler;
|
||||
|
||||
class QAction;
|
||||
class QNetworkAccessManager;
|
||||
class Song;
|
||||
|
||||
class LastFMService : public InternetService {
|
||||
class LastFMService : public Scrobbler {
|
||||
Q_OBJECT
|
||||
friend class LastFMUrlHandler;
|
||||
|
||||
public:
|
||||
LastFMService(Application* app, InternetModel* parent);
|
||||
LastFMService(Application* app, QObject* parent = nullptr);
|
||||
~LastFMService();
|
||||
|
||||
static const char* kServiceName;
|
||||
@ -61,34 +50,6 @@ class LastFMService : public InternetService {
|
||||
static const char* kApiKey;
|
||||
static const char* kSecret;
|
||||
|
||||
static const char* kUrlArtist;
|
||||
static const char* kUrlTag;
|
||||
static const char* kUrlCustom;
|
||||
|
||||
static const char* kTitleArtist;
|
||||
static const char* kTitleTag;
|
||||
static const char* kTitleCustom;
|
||||
|
||||
static const int kFriendsCacheDurationSecs;
|
||||
|
||||
enum ItemType {
|
||||
Type_Root = InternetModel::TypeCount,
|
||||
Type_Artists,
|
||||
Type_Tags,
|
||||
Type_Custom,
|
||||
Type_Friends,
|
||||
Type_Neighbours,
|
||||
Type_OtherUser,
|
||||
};
|
||||
|
||||
// InternetService
|
||||
QStandardItem* CreateRootItem();
|
||||
void LazyPopulate(QStandardItem* parent);
|
||||
|
||||
void ShowContextMenu(const QPoint& global_pos);
|
||||
|
||||
PlaylistItem::Options playlistitem_options() const;
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
virtual QString Icon() { return ":last.fm/lastfm.png"; }
|
||||
@ -106,18 +67,6 @@ class LastFMService : public InternetService {
|
||||
void SignOut();
|
||||
void UpdateSubscriberStatus();
|
||||
|
||||
void FetchMoreTracks();
|
||||
QUrl DeququeNextMediaUrl();
|
||||
|
||||
PlaylistItemPtr PlaylistItemForUrl(const QUrl& url);
|
||||
|
||||
bool IsFriendsListStale() const { return friend_names_.IsStale(); }
|
||||
|
||||
// Thread safe
|
||||
QStringList FriendNames();
|
||||
QStringList SavedArtistRadioNames() const;
|
||||
QStringList SavedTagRadioNames() const;
|
||||
|
||||
public slots:
|
||||
void NowPlaying(const Song& song);
|
||||
void Scrobble();
|
||||
@ -142,91 +91,35 @@ signals:
|
||||
private slots:
|
||||
void AuthenticateReplyFinished(QNetworkReply* reply);
|
||||
void UpdateSubscriberStatusFinished(QNetworkReply* reply);
|
||||
void RefreshFriendsFinished(QNetworkReply* reply);
|
||||
void RefreshNeighboursFinished(QNetworkReply* reply);
|
||||
|
||||
void TunerTrackAvailable();
|
||||
void TunerError(lastfm::ws::Error error);
|
||||
void ScrobblerStatus(int value);
|
||||
|
||||
void AddArtistRadio();
|
||||
void AddTagRadio();
|
||||
void AddCustomRadio();
|
||||
void ForceRefreshFriends();
|
||||
void RefreshFriends();
|
||||
void Remove();
|
||||
|
||||
// Radio tuner.
|
||||
void FetchMoreTracksFinished(QNetworkReply* reply);
|
||||
void TuneFinished(QNetworkReply* reply);
|
||||
|
||||
void StreamMetadataReady();
|
||||
|
||||
private:
|
||||
QStandardItem* CreateStationItem(QStandardItem* parent, const QString& name,
|
||||
const QString& icon, const QUrl& url,
|
||||
const QString& title);
|
||||
QString ErrorString(lastfm::ws::Error error) const;
|
||||
bool InitScrobbler();
|
||||
lastfm::Track TrackFromSong(const Song& song) const;
|
||||
void RefreshFriends(bool force);
|
||||
void RefreshNeighbours();
|
||||
void AddArtistOrTag(const QString& name,
|
||||
LastFMStationDialog::Type dialog_type,
|
||||
const QString& url_pattern, const QString& title_pattern,
|
||||
const QString& icon, QStandardItem* list);
|
||||
void SaveList(const QString& name, QStandardItem* list) const;
|
||||
void RestoreList(const QString& name, const QString& url_pattern,
|
||||
const QString& title_pattern, const QIcon& icon,
|
||||
QStandardItem* parent);
|
||||
|
||||
static QUrl FixupUrl(const QUrl& url);
|
||||
void Tune(const QUrl& station);
|
||||
|
||||
void PopulateFriendsList();
|
||||
|
||||
void AddSelectedToPlaylist(bool clear_first);
|
||||
|
||||
private:
|
||||
LastFMUrlHandler* url_handler_;
|
||||
|
||||
lastfm::Audioscrobbler* scrobbler_;
|
||||
lastfm::Track last_track_;
|
||||
lastfm::Track next_metadata_;
|
||||
QQueue<lastfm::Track> playlist_;
|
||||
bool already_scrobbled_;
|
||||
|
||||
std::unique_ptr<LastFMStationDialog> station_dialog_;
|
||||
|
||||
std::unique_ptr<QMenu> context_menu_;
|
||||
QAction* remove_action_;
|
||||
QAction* add_artist_action_;
|
||||
QAction* add_tag_action_;
|
||||
QAction* add_custom_action_;
|
||||
QAction* refresh_friends_action_;
|
||||
|
||||
QUrl last_url_;
|
||||
bool initial_tune_;
|
||||
int tune_task_id_;
|
||||
|
||||
bool scrobbling_enabled_;
|
||||
bool buttons_visible_;
|
||||
bool scrobble_button_visible_;
|
||||
bool prefer_albumartist_;
|
||||
|
||||
QStandardItem* root_item_;
|
||||
QStandardItem* artist_list_;
|
||||
QStandardItem* tag_list_;
|
||||
QStandardItem* custom_list_;
|
||||
QStandardItem* friends_list_;
|
||||
QStandardItem* neighbours_list_;
|
||||
|
||||
QHash<lastfm::Track, QString> art_urls_;
|
||||
|
||||
CachedList<QString> friend_names_;
|
||||
|
||||
// Useful to inform the user that we can't scrobble right now
|
||||
bool connection_problems_;
|
||||
|
||||
Application* app_;
|
||||
};
|
||||
|
||||
#endif // LASTFMSERVICE_H
|
||||
|
@ -16,21 +16,21 @@
|
||||
*/
|
||||
|
||||
#include "lastfmsettingspage.h"
|
||||
#include "lastfmservice.h"
|
||||
#include "internetmodel.h"
|
||||
#include "ui_lastfmsettingspage.h"
|
||||
#include "ui/iconloader.h"
|
||||
|
||||
#include <lastfm/ws.h>
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QMovie>
|
||||
#include <QSettings>
|
||||
|
||||
#include "lastfmservice.h"
|
||||
#include "internetmodel.h"
|
||||
#include "core/application.h"
|
||||
#include "ui/iconloader.h"
|
||||
|
||||
LastFMSettingsPage::LastFMSettingsPage(SettingsDialog* dialog)
|
||||
: SettingsPage(dialog),
|
||||
service_(
|
||||
static_cast<LastFMService*>(InternetModel::ServiceByName("Last.fm"))),
|
||||
service_(static_cast<LastFMService*>(dialog->app()->scrobbler())),
|
||||
ui_(new Ui_LastFMSettingsPage),
|
||||
waiting_for_auth_(false) {
|
||||
ui_->setupUi(this);
|
||||
@ -40,8 +40,6 @@ LastFMSettingsPage::LastFMSettingsPage(SettingsDialog* dialog)
|
||||
|
||||
connect(service_, SIGNAL(AuthenticationComplete(bool, QString)),
|
||||
SLOT(AuthenticationComplete(bool, QString)));
|
||||
connect(service_, SIGNAL(UpdatedSubscriberStatus(bool)),
|
||||
SLOT(UpdatedSubscriberStatus(bool)));
|
||||
connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(Logout()));
|
||||
connect(ui_->login_state, SIGNAL(LoginClicked()), SLOT(Login()));
|
||||
connect(ui_->login, SIGNAL(clicked()), SLOT(Login()));
|
||||
@ -83,7 +81,6 @@ void LastFMSettingsPage::AuthenticationComplete(bool success,
|
||||
}
|
||||
|
||||
RefreshControls(success);
|
||||
service_->UpdateSubscriberStatus();
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::Load() {
|
||||
@ -92,31 +89,9 @@ void LastFMSettingsPage::Load() {
|
||||
ui_->scrobble_button->setChecked(service_->IsScrobbleButtonVisible());
|
||||
ui_->prefer_albumartist->setChecked(service_->PreferAlbumArtist());
|
||||
|
||||
if (service_->IsAuthenticated()) {
|
||||
service_->UpdateSubscriberStatus();
|
||||
}
|
||||
|
||||
RefreshControls(service_->IsAuthenticated());
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::UpdatedSubscriberStatus(bool is_subscriber) {
|
||||
ui_->login_state->SetAccountTypeVisible(!is_subscriber);
|
||||
|
||||
if (!is_subscriber) {
|
||||
if (service_->HasConnectionProblems()) {
|
||||
ui_->login_state->SetAccountTypeText(
|
||||
tr("Clementine couldn't fetch your subscription status since there "
|
||||
"are problems "
|
||||
"with your connection. Played tracks will be cached and sent "
|
||||
"later to Last.fm."));
|
||||
} else {
|
||||
ui_->login_state->SetAccountTypeText(
|
||||
tr("You will not be able to play Last.fm radio stations "
|
||||
"as you are not a Last.fm subscriber."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::Save() {
|
||||
QSettings s;
|
||||
s.beginGroup(LastFMService::kSettingsGroup);
|
||||
@ -141,12 +116,4 @@ void LastFMSettingsPage::RefreshControls(bool authenticated) {
|
||||
ui_->login_state->SetLoggedIn(
|
||||
authenticated ? LoginStateWidget::LoggedIn : LoginStateWidget::LoggedOut,
|
||||
lastfm::ws::Username);
|
||||
ui_->login_state->SetAccountTypeVisible(!authenticated);
|
||||
|
||||
if (!authenticated) {
|
||||
ui_->login_state->SetAccountTypeText(
|
||||
tr("You can scrobble tracks for free, but only "
|
||||
"<span style=\" font-weight:600;\">paid subscribers</span> "
|
||||
"can stream Last.fm radio from Clementine."));
|
||||
}
|
||||
}
|
||||
|
@ -37,12 +37,10 @@ class LastFMSettingsPage : public SettingsPage {
|
||||
void Login();
|
||||
void AuthenticationComplete(bool success, const QString& error_message);
|
||||
void Logout();
|
||||
void UpdatedSubscriberStatus(bool is_subscriber);
|
||||
|
||||
private:
|
||||
LastFMService* service_;
|
||||
Ui_LastFMSettingsPage* ui_;
|
||||
QMovie* loading_icon_;
|
||||
|
||||
bool waiting_for_auth_;
|
||||
|
||||
|
@ -83,7 +83,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="love_ban_">
|
||||
<property name="text">
|
||||
<string>Show the "love" and "ban" buttons</string>
|
||||
<string>Show the "love" button</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "lastfmstationdialog.h"
|
||||
#include "ui_lastfmstationdialog.h"
|
||||
|
||||
LastFMStationDialog::LastFMStationDialog(QWidget* parent)
|
||||
: QDialog(parent), ui_(new Ui_LastFMStationDialog) {
|
||||
ui_->setupUi(this);
|
||||
|
||||
resize(sizeHint());
|
||||
}
|
||||
|
||||
LastFMStationDialog::~LastFMStationDialog() { delete ui_; }
|
||||
|
||||
void LastFMStationDialog::SetType(Type type) {
|
||||
ui_->type->setCurrentIndex(type);
|
||||
ui_->content->clear();
|
||||
ui_->content->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
QString LastFMStationDialog::content() const { return ui_->content->text(); }
|
@ -1,41 +0,0 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LASTFMSTATIONDIALOG_H
|
||||
#define LASTFMSTATIONDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class Ui_LastFMStationDialog;
|
||||
|
||||
class LastFMStationDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LastFMStationDialog(QWidget* parent = nullptr);
|
||||
~LastFMStationDialog();
|
||||
|
||||
enum Type { Artist, Tag, Custom, };
|
||||
|
||||
void SetType(Type type);
|
||||
QString content() const;
|
||||
|
||||
private:
|
||||
Ui_LastFMStationDialog* ui_;
|
||||
};
|
||||
|
||||
#endif // LASTFMSTATIONDIALOG_H
|
@ -1,119 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LastFMStationDialog</class>
|
||||
<widget class="QDialog" name="LastFMStationDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>407</width>
|
||||
<height>126</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Play Artist or Tag</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<normaloff>:/last.fm/as.png</normaloff>:/last.fm/as.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Enter an <b>artist</b> or <b>tag</b> to start listening to Last.fm radio.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="type">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Artist</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Tag</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="content"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>7</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>LastFMStationDialog</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>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>LastFMStationDialog</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,46 +0,0 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "lastfmservice.h"
|
||||
#include "lastfmurlhandler.h"
|
||||
|
||||
LastFMUrlHandler::LastFMUrlHandler(LastFMService* service, QObject* parent)
|
||||
: UrlHandler(parent), service_(service) {}
|
||||
|
||||
UrlHandler::LoadResult LastFMUrlHandler::StartLoading(const QUrl& url) {
|
||||
if (!service_->IsAuthenticated()) return LoadResult();
|
||||
|
||||
service_->Tune(url);
|
||||
return LoadResult(url, LoadResult::WillLoadAsynchronously);
|
||||
}
|
||||
|
||||
void LastFMUrlHandler::TunerTrackAvailable() {
|
||||
emit AsyncLoadComplete(LoadNext(service_->last_url_));
|
||||
}
|
||||
|
||||
void LastFMUrlHandler::TunerError() {
|
||||
emit AsyncLoadComplete(
|
||||
LoadResult(service_->last_url_, LoadResult::NoMoreTracks));
|
||||
}
|
||||
|
||||
UrlHandler::LoadResult LastFMUrlHandler::LoadNext(const QUrl& url) {
|
||||
const QUrl media_url = service_->DeququeNextMediaUrl();
|
||||
if (media_url.isEmpty()) {
|
||||
return LoadResult();
|
||||
}
|
||||
return LoadResult(url, LoadResult::TrackAvailable, media_url);
|
||||
}
|
36
src/internet/scrobbler.h
Normal file
36
src/internet/scrobbler.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef SCROBBLER_H
|
||||
#define SCROBBLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Song;
|
||||
|
||||
class Scrobbler : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Scrobbler(QObject* parent = nullptr) {}
|
||||
|
||||
virtual bool IsAuthenticated() const = 0;
|
||||
virtual bool IsScrobblingEnabled() const = 0;
|
||||
virtual bool AreButtonsVisible() const = 0;
|
||||
virtual bool IsScrobbleButtonVisible() const = 0;
|
||||
virtual bool PreferAlbumArtist() const = 0;
|
||||
|
||||
public slots:
|
||||
virtual void NowPlaying(const Song& song) = 0;
|
||||
virtual void Scrobble() = 0;
|
||||
virtual void Love() = 0;
|
||||
virtual void ToggleScrobbling() = 0;
|
||||
virtual void ShowConfig() = 0;
|
||||
|
||||
signals:
|
||||
void AuthenticationComplete(bool success, const QString& error_message);
|
||||
void ScrobblingEnabledChanged(bool value);
|
||||
void ButtonVisibilityChanged(bool value);
|
||||
void ScrobbleButtonVisibilityChanged(bool value);
|
||||
void ScrobbleSubmitted();
|
||||
void ScrobbleError(int value);
|
||||
};
|
||||
|
||||
#endif // SCROBBLER_H
|
@ -70,10 +70,7 @@ IncomingDataParser::IncomingDataParser(Application* app) : app_(app) {
|
||||
SLOT(RateCurrentSong(double)));
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
connect(this, SIGNAL(Love()), InternetModel::Service<LastFMService>(),
|
||||
SLOT(Love()));
|
||||
connect(this, SIGNAL(Ban()), InternetModel::Service<LastFMService>(),
|
||||
SLOT(Ban()));
|
||||
connect(this, SIGNAL(Love()), app_->scrobbler(), SLOT(Love()));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -261,7 +258,6 @@ void IncomingDataParser::RemoveSongs(const pb::remote::Message& msg) {
|
||||
}
|
||||
|
||||
void IncomingDataParser::ClientConnect(const pb::remote::Message& msg) {
|
||||
|
||||
// Always sned the Clementine infos
|
||||
emit SendClementineInfo();
|
||||
|
||||
|
@ -33,7 +33,7 @@ class MacSystemTrayIcon : public SystemTrayIcon {
|
||||
|
||||
void SetupMenu(QAction* previous, QAction* play, QAction* stop,
|
||||
QAction* stop_after, QAction* next, QAction* mute,
|
||||
QAction* love, QAction* ban, QAction* quit);
|
||||
QAction* love, QAction* quit);
|
||||
|
||||
void SetNowPlaying(const Song& song, const QString& image_path);
|
||||
void ClearNowPlaying();
|
||||
|
@ -177,7 +177,7 @@ MacSystemTrayIcon::~MacSystemTrayIcon() {}
|
||||
void MacSystemTrayIcon::SetupMenu(QAction* previous, QAction* play,
|
||||
QAction* stop, QAction* stop_after,
|
||||
QAction* next, QAction* mute, QAction* love,
|
||||
QAction* ban, QAction* quit) {
|
||||
QAction* quit) {
|
||||
p_.reset(new MacSystemTrayIconPrivate());
|
||||
SetupMenuItem(previous);
|
||||
SetupMenuItem(play);
|
||||
@ -188,7 +188,6 @@ void MacSystemTrayIcon::SetupMenu(QAction* previous, QAction* play,
|
||||
SetupMenuItem(mute);
|
||||
p_->AddSeparator();
|
||||
SetupMenuItem(love);
|
||||
SetupMenuItem(ban);
|
||||
Q_UNUSED(quit); // Mac already has a Quit item.
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VK
|
||||
# include "internet/vkservice.h"
|
||||
#include "internet/vkservice.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
@ -342,11 +342,9 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
SLOT(StopAfterCurrent()));
|
||||
connect(ui_->action_mute, SIGNAL(triggered()), app_->player(), SLOT(Mute()));
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
connect(ui_->action_ban, SIGNAL(triggered()),
|
||||
InternetModel::Service<LastFMService>(), SLOT(Ban()));
|
||||
connect(ui_->action_love, SIGNAL(triggered()), SLOT(Love()));
|
||||
connect(ui_->action_toggle_scrobbling, SIGNAL(triggered()),
|
||||
InternetModel::Service<LastFMService>(), SLOT(ToggleScrobbling()));
|
||||
connect(ui_->action_toggle_scrobbling, SIGNAL(triggered()), app_->scrobbler(),
|
||||
SLOT(ToggleScrobbling()));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VK
|
||||
@ -424,7 +422,6 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
ui_->pause_play_button->setDefaultAction(ui_->action_play_pause);
|
||||
ui_->stop_button->setDefaultAction(ui_->action_stop);
|
||||
ui_->love_button->setDefaultAction(ui_->action_love);
|
||||
ui_->ban_button->setDefaultAction(ui_->action_ban);
|
||||
ui_->scrobbling_button->setDefaultAction(ui_->action_toggle_scrobbling);
|
||||
ui_->clear_playlist_button->setDefaultAction(ui_->action_clear_playlist);
|
||||
ui_->playlist->SetActions(
|
||||
@ -654,14 +651,13 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
connect(app_->internet_model(), SIGNAL(ScrollToIndex(QModelIndex)),
|
||||
SLOT(ScrollToInternetIndex(QModelIndex)));
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
LastFMService* lastfm_service = InternetModel::Service<LastFMService>();
|
||||
connect(lastfm_service, SIGNAL(ButtonVisibilityChanged(bool)),
|
||||
connect(app_->scrobbler(), SIGNAL(ButtonVisibilityChanged(bool)),
|
||||
SLOT(LastFMButtonVisibilityChanged(bool)));
|
||||
connect(lastfm_service, SIGNAL(ScrobbleButtonVisibilityChanged(bool)),
|
||||
connect(app_->scrobbler(), SIGNAL(ScrobbleButtonVisibilityChanged(bool)),
|
||||
SLOT(ScrobbleButtonVisibilityChanged(bool)));
|
||||
connect(lastfm_service, SIGNAL(ScrobblingEnabledChanged(bool)),
|
||||
connect(app_->scrobbler(), SIGNAL(ScrobblingEnabledChanged(bool)),
|
||||
SLOT(ScrobblingEnabledChanged(bool)));
|
||||
connect(lastfm_service, SIGNAL(ScrobbledRadioStream()),
|
||||
connect(app_->scrobbler(), SIGNAL(ScrobbledRadioStream()),
|
||||
SLOT(ScrobbledRadioStream()));
|
||||
#endif
|
||||
connect(app_->internet_model()->Service<MagnatuneService>(),
|
||||
@ -681,7 +677,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
tray_icon_->SetupMenu(ui_->action_previous_track, ui_->action_play_pause,
|
||||
ui_->action_stop, ui_->action_stop_after_this_track,
|
||||
ui_->action_next_track, ui_->action_mute,
|
||||
ui_->action_love, ui_->action_ban, ui_->action_quit);
|
||||
ui_->action_love, ui_->action_quit);
|
||||
connect(tray_icon_, SIGNAL(PlayPause()), app_->player(), SLOT(PlayPause()));
|
||||
connect(tray_icon_, SIGNAL(SeekForward()), app_->player(),
|
||||
SLOT(SeekForward()));
|
||||
@ -698,7 +694,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
<< ui_->action_previous_track << ui_->action_play_pause
|
||||
<< ui_->action_stop << ui_->action_next_track
|
||||
<< nullptr // spacer
|
||||
<< ui_->action_love << ui_->action_ban);
|
||||
<< ui_->action_love);
|
||||
|
||||
#if (defined(Q_OS_DARWIN) && defined(HAVE_SPARKLE)) || defined(Q_OS_WIN32)
|
||||
// Add check for updates item to application menu.
|
||||
@ -744,8 +740,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
connect(global_shortcuts_, SIGNAL(TogglePrettyOSD()), app_->player(),
|
||||
SLOT(TogglePrettyOSD()));
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
connect(global_shortcuts_, SIGNAL(ToggleScrobbling()),
|
||||
app_->internet_model()->InternetModel::Service<LastFMService>(),
|
||||
connect(global_shortcuts_, SIGNAL(ToggleScrobbling()), app_->scrobbler(),
|
||||
SLOT(ToggleScrobbling()));
|
||||
#endif
|
||||
|
||||
@ -844,20 +839,14 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
SLOT(ShuffleModeChanged(PlaylistSequence::ShuffleMode)));
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
connect(InternetModel::Service<LastFMService>(), SIGNAL(ScrobbleSubmitted()),
|
||||
connect(app_->scrobbler(), SIGNAL(ScrobbleSubmitted()),
|
||||
SLOT(ScrobbleSubmitted()));
|
||||
connect(InternetModel::Service<LastFMService>(), SIGNAL(ScrobbleError(int)),
|
||||
connect(app_->scrobbler(), SIGNAL(ScrobbleError(int)),
|
||||
SLOT(ScrobbleError(int)));
|
||||
|
||||
LastFMButtonVisibilityChanged(app_->internet_model()
|
||||
->InternetModel::Service<LastFMService>()
|
||||
->AreButtonsVisible());
|
||||
ScrobbleButtonVisibilityChanged(app_->internet_model()
|
||||
->InternetModel::Service<LastFMService>()
|
||||
->IsScrobbleButtonVisible());
|
||||
ScrobblingEnabledChanged(app_->internet_model()
|
||||
->InternetModel::Service<LastFMService>()
|
||||
->IsScrobblingEnabled());
|
||||
LastFMButtonVisibilityChanged(app_->scrobbler()->AreButtonsVisible());
|
||||
ScrobbleButtonVisibilityChanged(app_->scrobbler()->IsScrobbleButtonVisible());
|
||||
ScrobblingEnabledChanged(app_->scrobbler()->IsScrobblingEnabled());
|
||||
#else
|
||||
LastFMButtonVisibilityChanged(false);
|
||||
ScrobbleButtonVisibilityChanged(false);
|
||||
@ -869,7 +858,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
|
||||
restoreGeometry(settings_.value("geometry").toByteArray());
|
||||
if (!ui_->splitter->restoreState(
|
||||
settings_.value("splitter_state").toByteArray())) {
|
||||
settings_.value("splitter_state").toByteArray())) {
|
||||
ui_->splitter->setSizes(QList<int>() << 300 << width() - 300);
|
||||
}
|
||||
ui_->tabs->SetCurrentIndex(
|
||||
@ -989,10 +978,8 @@ void MainWindow::MediaStopped() {
|
||||
|
||||
ui_->action_play_pause->setEnabled(true);
|
||||
|
||||
ui_->action_ban->setEnabled(false);
|
||||
ui_->action_love->setEnabled(false);
|
||||
tray_icon_->LastFMButtonLoveStateChanged(false);
|
||||
tray_icon_->LastFMButtonBanStateChanged(false);
|
||||
|
||||
track_position_timer_->stop();
|
||||
ui_->track_slider->SetStopped();
|
||||
@ -1028,18 +1015,10 @@ void MainWindow::MediaPlaying() {
|
||||
ui_->track_slider->SetCanSeek(can_seek);
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
bool is_lastfm = (app_->player()->GetCurrentItem()->options() &
|
||||
PlaylistItem::LastFMControls);
|
||||
LastFMService* lastfm = InternetModel::Service<LastFMService>();
|
||||
bool enable_ban = lastfm->IsScrobblingEnabled() && is_lastfm;
|
||||
bool enable_love = lastfm->IsScrobblingEnabled();
|
||||
|
||||
ui_->action_ban->setEnabled(enable_ban);
|
||||
bool enable_love = app_->scrobbler()->IsScrobblingEnabled();
|
||||
ui_->action_love->setEnabled(enable_love);
|
||||
tray_icon_->LastFMButtonBanStateChanged(enable_ban);
|
||||
tray_icon_->LastFMButtonLoveStateChanged(enable_love);
|
||||
|
||||
tray_icon_->SetPlaying(enable_play_pause, enable_ban, enable_love);
|
||||
tray_icon_->SetPlaying(enable_play_pause, enable_love);
|
||||
#else
|
||||
tray_icon_->SetPlaying(enable_play_pause);
|
||||
#endif
|
||||
@ -1059,8 +1038,7 @@ void MainWindow::SongChanged(const Song& song) {
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
if (ui_->action_toggle_scrobbling->isVisible())
|
||||
SetToggleScrobblingIcon(
|
||||
InternetModel::Service<LastFMService>()->IsScrobblingEnabled());
|
||||
SetToggleScrobblingIcon(app_->scrobbler()->IsScrobblingEnabled());
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1104,17 +1082,12 @@ void MainWindow::ScrobblingEnabledChanged(bool value) {
|
||||
}
|
||||
}
|
||||
|
||||
bool is_lastfm = (app_->player()->GetCurrentItem()->options() &
|
||||
PlaylistItem::LastFMControls);
|
||||
ui_->action_ban->setEnabled(value && is_lastfm);
|
||||
tray_icon_->LastFMButtonBanStateChanged(value && is_lastfm);
|
||||
ui_->action_love->setEnabled(value);
|
||||
tray_icon_->LastFMButtonLoveStateChanged(value);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainWindow::LastFMButtonVisibilityChanged(bool value) {
|
||||
ui_->action_ban->setVisible(value);
|
||||
ui_->action_love->setVisible(value);
|
||||
ui_->last_fm_controls->setVisible(value);
|
||||
tray_icon_->LastFMButtonVisibilityChanged(value);
|
||||
@ -1132,9 +1105,7 @@ void MainWindow::ScrobbleButtonVisibilityChanged(bool value) {
|
||||
ui_->action_toggle_scrobbling->setIcon(QIcon(":/last.fm/as.png"));
|
||||
} else {
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
SetToggleScrobblingIcon(app_->internet_model()
|
||||
->InternetModel::Service<LastFMService>()
|
||||
->IsScrobblingEnabled());
|
||||
SetToggleScrobblingIcon(app_->scrobbler()->IsScrobblingEnabled());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1300,20 +1271,19 @@ void MainWindow::UpdateTrackPosition() {
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
LastFMService* lastfm_service = InternetModel::Service<LastFMService>();
|
||||
const bool last_fm_enabled = ui_->action_toggle_scrobbling->isVisible() &&
|
||||
lastfm_service->IsScrobblingEnabled() &&
|
||||
lastfm_service->IsAuthenticated();
|
||||
app_->scrobbler()->IsScrobblingEnabled() &&
|
||||
app_->scrobbler()->IsAuthenticated();
|
||||
#endif
|
||||
|
||||
// Time to scrobble?
|
||||
if (position >= scrobble_point) {
|
||||
if (playlist->get_lastfm_status() == Playlist::LastFM_New) {
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
if (lastfm_service->IsScrobblingEnabled() &&
|
||||
lastfm_service->IsAuthenticated()) {
|
||||
if (app_->scrobbler()->IsScrobblingEnabled() &&
|
||||
app_->scrobbler()->IsAuthenticated()) {
|
||||
qLog(Info) << "Scrobbling at" << scrobble_point;
|
||||
lastfm_service->Scrobble();
|
||||
app_->scrobbler()->Scrobble();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1355,7 +1325,7 @@ void MainWindow::ScrobbledRadioStream() {
|
||||
}
|
||||
|
||||
void MainWindow::Love() {
|
||||
InternetModel::Service<LastFMService>()->Love();
|
||||
app_->scrobbler()->Love();
|
||||
ui_->action_love->setEnabled(false);
|
||||
tray_icon_->LastFMButtonLoveStateChanged(false);
|
||||
}
|
||||
@ -1432,10 +1402,8 @@ void MainWindow::AddToPlaylist(QAction* action) {
|
||||
PlaylistItemList items;
|
||||
|
||||
// get the selected playlist items
|
||||
for (const QModelIndex& index : ui_->playlist->view()
|
||||
->selectionModel()
|
||||
->selection()
|
||||
.indexes()) {
|
||||
for (const QModelIndex& index :
|
||||
ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
if (index.column() != 0) continue;
|
||||
int row =
|
||||
app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
@ -1693,10 +1661,8 @@ void MainWindow::EditTracks() {
|
||||
SongList songs;
|
||||
PlaylistItemList items;
|
||||
|
||||
for (const QModelIndex& index : ui_->playlist->view()
|
||||
->selectionModel()
|
||||
->selection()
|
||||
.indexes()) {
|
||||
for (const QModelIndex& index :
|
||||
ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
if (index.column() != 0) continue;
|
||||
int row =
|
||||
app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
@ -2078,10 +2044,8 @@ void MainWindow::AddFilesToTranscoder() {
|
||||
|
||||
QStringList filenames;
|
||||
|
||||
for (const QModelIndex& index : ui_->playlist->view()
|
||||
->selectionModel()
|
||||
->selection()
|
||||
.indexes()) {
|
||||
for (const QModelIndex& index :
|
||||
ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
if (index.column() != 0) continue;
|
||||
int row =
|
||||
app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
@ -2249,9 +2213,8 @@ void MainWindow::DeleteFinished(const SongList& songs_with_errors) {
|
||||
|
||||
void MainWindow::PlaylistQueue() {
|
||||
QModelIndexList indexes;
|
||||
for (const QModelIndex& proxy_index : ui_->playlist->view()
|
||||
->selectionModel()
|
||||
->selectedRows()) {
|
||||
for (const QModelIndex& proxy_index :
|
||||
ui_->playlist->view()->selectionModel()->selectedRows()) {
|
||||
indexes << app_->playlist_manager()->current()->proxy()->mapToSource(
|
||||
proxy_index);
|
||||
}
|
||||
@ -2261,9 +2224,8 @@ void MainWindow::PlaylistQueue() {
|
||||
|
||||
void MainWindow::PlaylistSkip() {
|
||||
QModelIndexList indexes;
|
||||
for (const QModelIndex& proxy_index : ui_->playlist->view()
|
||||
->selectionModel()
|
||||
->selectedRows()) {
|
||||
for (const QModelIndex& proxy_index :
|
||||
ui_->playlist->view()->selectionModel()->selectedRows()) {
|
||||
indexes << app_->playlist_manager()->current()->proxy()->mapToSource(
|
||||
proxy_index);
|
||||
}
|
||||
@ -2545,10 +2507,8 @@ void MainWindow::AutoCompleteTags() {
|
||||
// Get the selected songs and start fetching tags for them
|
||||
SongList songs;
|
||||
autocomplete_tag_items_.clear();
|
||||
for (const QModelIndex& index : ui_->playlist->view()
|
||||
->selectionModel()
|
||||
->selection()
|
||||
.indexes()) {
|
||||
for (const QModelIndex& index :
|
||||
ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
if (index.column() != 0) continue;
|
||||
int row =
|
||||
app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
@ -2613,10 +2573,9 @@ void MainWindow::SetToggleScrobblingIcon(bool value) {
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
void MainWindow::ScrobbleSubmitted() {
|
||||
const LastFMService* lastfm_service = InternetModel::Service<LastFMService>();
|
||||
const bool last_fm_enabled = ui_->action_toggle_scrobbling->isVisible() &&
|
||||
lastfm_service->IsScrobblingEnabled() &&
|
||||
lastfm_service->IsAuthenticated();
|
||||
app_->scrobbler()->IsScrobblingEnabled() &&
|
||||
app_->scrobbler()->IsAuthenticated();
|
||||
|
||||
app_->playlist_manager()->active()->set_lastfm_status(
|
||||
Playlist::LastFM_Scrobbled);
|
||||
|
@ -200,19 +200,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="ban_button">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -435,7 +422,6 @@
|
||||
<addaction name="action_mute"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_love"/>
|
||||
<addaction name="action_ban"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_quit"/>
|
||||
</widget>
|
||||
@ -567,21 +553,6 @@
|
||||
<string>Ctrl+L</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_ban">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<normaloff>:/last.fm/ban.png</normaloff>:/last.fm/ban.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ban</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+B</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_clear_playlist">
|
||||
<property name="text">
|
||||
<string>Clear playlist</string>
|
||||
|
@ -36,8 +36,7 @@ QtSystemTrayIcon::QtSystemTrayIcon(QObject* parent)
|
||||
action_stop_(nullptr),
|
||||
action_stop_after_this_track_(nullptr),
|
||||
action_mute_(nullptr),
|
||||
action_love_(nullptr),
|
||||
action_ban_(nullptr) {
|
||||
action_love_(nullptr) {
|
||||
QIcon theme_icon = IconLoader::Load("clementine-panel");
|
||||
QIcon theme_icon_grey = IconLoader::Load("clementine-panel-grey");
|
||||
|
||||
@ -97,7 +96,7 @@ bool QtSystemTrayIcon::eventFilter(QObject* object, QEvent* event) {
|
||||
void QtSystemTrayIcon::SetupMenu(QAction* previous, QAction* play,
|
||||
QAction* stop, QAction* stop_after,
|
||||
QAction* next, QAction* mute, QAction* love,
|
||||
QAction* ban, QAction* quit) {
|
||||
QAction* quit) {
|
||||
// Creating new actions and connecting them to old ones. This allows us to
|
||||
// use old actions without displaying shortcuts that can not be used when
|
||||
// Clementine's window is hidden
|
||||
@ -123,10 +122,6 @@ void QtSystemTrayIcon::SetupMenu(QAction* previous, QAction* play,
|
||||
menu_->addAction(love->icon(), love->text(), love, SLOT(trigger()));
|
||||
action_love_->setVisible(love->isVisible());
|
||||
action_love_->setEnabled(love->isEnabled());
|
||||
action_ban_ =
|
||||
menu_->addAction(ban->icon(), ban->text(), ban, SLOT(trigger()));
|
||||
action_ban_->setVisible(ban->isVisible());
|
||||
action_ban_->setEnabled(ban->isEnabled());
|
||||
#endif
|
||||
|
||||
menu_->addSeparator();
|
||||
@ -171,8 +166,7 @@ void QtSystemTrayIcon::SetPaused() {
|
||||
action_play_pause_->setEnabled(true);
|
||||
}
|
||||
|
||||
void QtSystemTrayIcon::SetPlaying(bool enable_play_pause, bool enable_ban,
|
||||
bool enable_love) {
|
||||
void QtSystemTrayIcon::SetPlaying(bool enable_play_pause, bool enable_love) {
|
||||
SystemTrayIcon::SetPlaying();
|
||||
|
||||
action_stop_->setEnabled(true);
|
||||
@ -181,7 +175,6 @@ void QtSystemTrayIcon::SetPlaying(bool enable_play_pause, bool enable_ban,
|
||||
action_play_pause_->setText(tr("Pause"));
|
||||
action_play_pause_->setEnabled(enable_play_pause);
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
action_ban_->setEnabled(enable_ban);
|
||||
action_love_->setEnabled(enable_love);
|
||||
#endif
|
||||
}
|
||||
@ -197,14 +190,12 @@ void QtSystemTrayIcon::SetStopped() {
|
||||
action_play_pause_->setEnabled(true);
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
action_ban_->setEnabled(false);
|
||||
action_love_->setEnabled(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void QtSystemTrayIcon::LastFMButtonVisibilityChanged(bool value) {
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
action_ban_->setVisible(value);
|
||||
action_love_->setVisible(value);
|
||||
#endif
|
||||
}
|
||||
@ -215,12 +206,6 @@ void QtSystemTrayIcon::LastFMButtonLoveStateChanged(bool value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void QtSystemTrayIcon::LastFMButtonBanStateChanged(bool value) {
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
action_ban_->setEnabled(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
void QtSystemTrayIcon::MuteButtonStateChanged(bool value) {
|
||||
if (action_mute_) action_mute_->setChecked(value);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class QtSystemTrayIcon : public SystemTrayIcon {
|
||||
|
||||
void SetupMenu(QAction* previous, QAction* play, QAction* stop,
|
||||
QAction* stop_after, QAction* next, QAction* mute,
|
||||
QAction* love, QAction* ban, QAction* quit);
|
||||
QAction* love, QAction* quit);
|
||||
bool IsVisible() const;
|
||||
void SetVisible(bool visible);
|
||||
|
||||
@ -44,12 +44,10 @@ class QtSystemTrayIcon : public SystemTrayIcon {
|
||||
// SystemTrayIcon
|
||||
void UpdateIcon();
|
||||
void SetPaused();
|
||||
void SetPlaying(bool enable_play_pause = false, bool enable_ban = false,
|
||||
bool enable_love = false);
|
||||
void SetPlaying(bool enable_play_pause = false, bool enable_love = false);
|
||||
void SetStopped();
|
||||
void LastFMButtonVisibilityChanged(bool value);
|
||||
void LastFMButtonLoveStateChanged(bool value);
|
||||
void LastFMButtonBanStateChanged(bool value);
|
||||
void MuteButtonStateChanged(bool value);
|
||||
|
||||
// QObject
|
||||
@ -66,7 +64,6 @@ class QtSystemTrayIcon : public SystemTrayIcon {
|
||||
QAction* action_stop_after_this_track_;
|
||||
QAction* action_mute_;
|
||||
QAction* action_love_;
|
||||
QAction* action_ban_;
|
||||
|
||||
QString pattern_;
|
||||
|
||||
|
@ -86,8 +86,7 @@ void SystemTrayIcon::SetPaused() {
|
||||
UpdateIcon();
|
||||
}
|
||||
|
||||
void SystemTrayIcon::SetPlaying(bool enable_play_pause, bool enable_ban,
|
||||
bool enable_love) {
|
||||
void SystemTrayIcon::SetPlaying(bool enable_play_pause, bool enable_love) {
|
||||
current_state_icon_ = playing_icon_;
|
||||
UpdateIcon();
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ class SystemTrayIcon : public QObject {
|
||||
// Called once to create the icon's context menu
|
||||
virtual void SetupMenu(QAction* previous, QAction* play, QAction* stop,
|
||||
QAction* stop_after, QAction* next, QAction* mute,
|
||||
QAction* love, QAction* ban, QAction* quit) = 0;
|
||||
QAction* love, QAction* quit) = 0;
|
||||
|
||||
virtual bool IsVisible() const { return true; }
|
||||
virtual void SetVisible(bool visible) {}
|
||||
@ -54,11 +54,10 @@ class SystemTrayIcon : public QObject {
|
||||
void SetProgress(int percentage);
|
||||
virtual void SetPaused();
|
||||
virtual void SetPlaying(bool enable_play_pause = false,
|
||||
bool enable_ban = false, bool enable_love = false);
|
||||
bool enable_love = false);
|
||||
virtual void SetStopped();
|
||||
virtual void LastFMButtonVisibilityChanged(bool value) {}
|
||||
virtual void LastFMButtonLoveStateChanged(bool value) {}
|
||||
virtual void LastFMButtonBanStateChanged(bool value) {}
|
||||
virtual void MuteButtonStateChanged(bool value) {}
|
||||
|
||||
signals:
|
||||
|
Loading…
x
Reference in New Issue
Block a user