Last.fm global search provider
This commit is contained in:
parent
d83736acc0
commit
cc20d90a7a
@ -659,6 +659,7 @@ endif(ENABLE_VISUALISATIONS)
|
|||||||
if(HAVE_LIBLASTFM)
|
if(HAVE_LIBLASTFM)
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
covers/lastfmcoverprovider.cpp
|
covers/lastfmcoverprovider.cpp
|
||||||
|
globalsearch/lastfmsearchprovider.cpp
|
||||||
internet/fixlastfm.cpp
|
internet/fixlastfm.cpp
|
||||||
internet/lastfmservice.cpp
|
internet/lastfmservice.cpp
|
||||||
internet/lastfmsettingspage.cpp
|
internet/lastfmsettingspage.cpp
|
||||||
@ -672,6 +673,7 @@ if(HAVE_LIBLASTFM)
|
|||||||
)
|
)
|
||||||
list(APPEND HEADERS
|
list(APPEND HEADERS
|
||||||
covers/lastfmcoverprovider.h
|
covers/lastfmcoverprovider.h
|
||||||
|
globalsearch/lastfmsearchprovider.h
|
||||||
internet/lastfmservice.h
|
internet/lastfmservice.h
|
||||||
internet/lastfmsettingspage.h
|
internet/lastfmsettingspage.h
|
||||||
internet/lastfmstationdialog.h
|
internet/lastfmstationdialog.h
|
||||||
|
@ -91,6 +91,10 @@ void GlobalSearchItemDelegate::paint(QPainter* p,
|
|||||||
case SearchProvider::Result::Type_Track:
|
case SearchProvider::Result::Type_Track:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SearchProvider::Result::Type_Stream:
|
||||||
|
count = QString::fromUtf8("∞");
|
||||||
|
break;
|
||||||
|
|
||||||
case SearchProvider::Result::Type_Album:
|
case SearchProvider::Result::Type_Album:
|
||||||
if (result.album_size_ <= 0)
|
if (result.album_size_ <= 0)
|
||||||
count = "-";
|
count = "-";
|
||||||
@ -126,7 +130,8 @@ void GlobalSearchItemDelegate::paint(QPainter* p,
|
|||||||
|
|
||||||
// The text we draw depends on the type of result.
|
// The text we draw depends on the type of result.
|
||||||
switch (result.type_) {
|
switch (result.type_) {
|
||||||
case SearchProvider::Result::Type_Track: {
|
case SearchProvider::Result::Type_Track:
|
||||||
|
case SearchProvider::Result::Type_Stream: {
|
||||||
// Title
|
// Title
|
||||||
line_1 += m.title() + " ";
|
line_1 += m.title() + " ";
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ bool GlobalSearchSortModel::lessThan(const QModelIndex& left, const QModelIndex&
|
|||||||
// Then compare title, artist and album
|
// Then compare title, artist and album
|
||||||
switch (r1.type_) {
|
switch (r1.type_) {
|
||||||
case SearchProvider::Result::Type_Track:
|
case SearchProvider::Result::Type_Track:
|
||||||
|
case SearchProvider::Result::Type_Stream:
|
||||||
CompareString(title);
|
CompareString(title);
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case SearchProvider::Result::Type_Album:
|
case SearchProvider::Result::Type_Album:
|
||||||
|
@ -112,8 +112,12 @@ GlobalSearchWidget::~GlobalSearchWidget() {
|
|||||||
|
|
||||||
void GlobalSearchWidget::Init(GlobalSearch* engine) {
|
void GlobalSearchWidget::Init(GlobalSearch* engine) {
|
||||||
engine_ = engine;
|
engine_ = engine;
|
||||||
|
|
||||||
|
// These have to be queued connections because they may get emitted before
|
||||||
|
// our call to Search() (or whatever) returns and we add the ID to the map.
|
||||||
connect(engine_, SIGNAL(ResultsAvailable(int,SearchProvider::ResultList)),
|
connect(engine_, SIGNAL(ResultsAvailable(int,SearchProvider::ResultList)),
|
||||||
SLOT(AddResults(int,SearchProvider::ResultList)));
|
SLOT(AddResults(int,SearchProvider::ResultList)),
|
||||||
|
Qt::QueuedConnection);
|
||||||
connect(engine_, SIGNAL(SearchFinished(int)), SLOT(SearchFinished(int)),
|
connect(engine_, SIGNAL(SearchFinished(int)), SLOT(SearchFinished(int)),
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
connect(engine_, SIGNAL(ArtLoaded(int,QPixmap)), SLOT(ArtLoaded(int,QPixmap)),
|
connect(engine_, SIGNAL(ArtLoaded(int,QPixmap)), SLOT(ArtLoaded(int,QPixmap)),
|
||||||
@ -555,6 +559,10 @@ GlobalSearchWidget::CombineAction GlobalSearchWidget::CanCombineResults(
|
|||||||
if (StringsDiffer(album) || StringsDiffer(artist))
|
if (StringsDiffer(album) || StringsDiffer(artist))
|
||||||
return CannotCombine;
|
return CannotCombine;
|
||||||
break;
|
break;
|
||||||
|
case SearchProvider::Result::Type_Stream:
|
||||||
|
if (StringsDiffer(url().toString))
|
||||||
|
return CannotCombine;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef StringsDiffer
|
#undef StringsDiffer
|
||||||
|
148
src/globalsearch/lastfmsearchprovider.cpp
Normal file
148
src/globalsearch/lastfmsearchprovider.cpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/* 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"
|
||||||
|
#include "playlist/songmimedata.h"
|
||||||
|
|
||||||
|
const int LastFMSearchProvider::kResultLimit = 6;
|
||||||
|
|
||||||
|
|
||||||
|
LastFMSearchProvider::LastFMSearchProvider(LastFMService* service, QObject* parent)
|
||||||
|
: BlockingSearchProvider(parent),
|
||||||
|
service_(service) {
|
||||||
|
Init("Last.fm", "lastfm", QIcon(":last.fm/as.png"), false, true);
|
||||||
|
icon_ = ScaleAndPad(QImage(":last.fm/as.png"));
|
||||||
|
|
||||||
|
connect(service, SIGNAL(SavedItemsChanged()), SLOT(RecreateItems()));
|
||||||
|
RecreateItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchProvider::ResultList LastFMSearchProvider::Search(int id, const QString& query) {
|
||||||
|
ResultList ret;
|
||||||
|
const QStringList tokens = TokenizeQuery(query);
|
||||||
|
|
||||||
|
QMutexLocker l(&items_mutex_);
|
||||||
|
foreach (const Item& item, items_) {
|
||||||
|
Result result(this);
|
||||||
|
result.type_ = Result::Type_Stream;
|
||||||
|
result.match_quality_ = Result::Quality_None;
|
||||||
|
|
||||||
|
foreach (const QString& token, tokens) {
|
||||||
|
if (item.keyword_.startsWith(token, Qt::CaseInsensitive)) {
|
||||||
|
result.match_quality_ = Result::Quality_AtStart;
|
||||||
|
result.metadata_ = item.metadata_;
|
||||||
|
break; // Next item
|
||||||
|
}
|
||||||
|
|
||||||
|
Result::MatchQuality quality = MatchQuality(tokens, item.metadata_.title());
|
||||||
|
if (quality == Result::Quality_None)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result.match_quality_ = qMin(quality, result.match_quality_);
|
||||||
|
result.metadata_ = item.metadata_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.match_quality_ != Result::Quality_None) {
|
||||||
|
ret << result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret.count() >= kResultLimit)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::LoadTracksAsync(int id, const Result& result) {
|
||||||
|
Song metadata = result.metadata_;
|
||||||
|
metadata.set_filetype(Song::Type_Stream);
|
||||||
|
|
||||||
|
SongMimeData* mime_data = new SongMimeData;
|
||||||
|
mime_data->songs = SongList() << metadata;
|
||||||
|
|
||||||
|
emit TracksLoaded(id, mime_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LastFMSearchProvider::RecreateItems() {
|
||||||
|
QList<Item> items;
|
||||||
|
Item item;
|
||||||
|
|
||||||
|
item.keyword_ = "recommended";
|
||||||
|
item.metadata_.set_title(tr("My Last.fm Recommended Radio"));
|
||||||
|
item.metadata_.set_url(QUrl("lastfm://user/USERNAME/recommended"));
|
||||||
|
items << item;
|
||||||
|
|
||||||
|
item.keyword_ = "radio";
|
||||||
|
item.metadata_.set_title(tr("My Last.fm Library"));
|
||||||
|
item.metadata_.set_url(QUrl("lastfm://user/USERNAME/library"));
|
||||||
|
items << item;
|
||||||
|
|
||||||
|
item.keyword_ = "mix";
|
||||||
|
item.metadata_.set_title(tr("My Last.fm Mix Radio"));
|
||||||
|
item.metadata_.set_url(QUrl("lastfm://user/USERNAME/mix"));
|
||||||
|
items << item;
|
||||||
|
|
||||||
|
item.keyword_ = "neighborhood";
|
||||||
|
item.metadata_.set_title(tr("My Last.fm Neighborhood"));
|
||||||
|
item.metadata_.set_url(QUrl("lastfm://user/USERNAME/neighbours"));
|
||||||
|
items << item;
|
||||||
|
|
||||||
|
const QStringList artists = service_->SavedArtistRadioNames();
|
||||||
|
const QStringList tags = service_->SavedTagRadioNames();
|
||||||
|
const QStringList friends = service_->FriendNames();
|
||||||
|
|
||||||
|
foreach (const QString& name, artists) {
|
||||||
|
item.keyword_ = name;
|
||||||
|
item.metadata_.set_title(tr(LastFMService::kTitleArtist).arg(name));
|
||||||
|
item.metadata_.set_url(QUrl(QString(LastFMService::kUrlArtist).arg(name)));
|
||||||
|
items << item;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QString& name, tags) {
|
||||||
|
item.keyword_ = name;
|
||||||
|
item.metadata_.set_title(tr(LastFMService::kTitleTag).arg(name));
|
||||||
|
item.metadata_.set_url(QUrl(QString(LastFMService::kUrlTag).arg(name)));
|
||||||
|
items << item;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (const QString& name, friends) {
|
||||||
|
item.keyword_ = name;
|
||||||
|
|
||||||
|
item.metadata_.set_title(tr("Last.fm Radio Station - %1").arg(name));
|
||||||
|
item.metadata_.set_url(QUrl("lastfm://user/" + name + "/library"));
|
||||||
|
items << item;
|
||||||
|
|
||||||
|
item.metadata_.set_title(tr("Last.fm Mix Radio - %1").arg(name));
|
||||||
|
item.metadata_.set_url(QUrl("lastfm://user/" + name + "/mix"));
|
||||||
|
items << item;
|
||||||
|
|
||||||
|
item.metadata_.set_title(tr("Last.fm Neighbor Radio - %1").arg(name));
|
||||||
|
item.metadata_.set_url(QUrl("lastfm://user/" + name + "/neighbours"));
|
||||||
|
items << item;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMutexLocker l(&items_mutex_);
|
||||||
|
items_ = items;
|
||||||
|
}
|
56
src/globalsearch/lastfmsearchprovider.h
Normal file
56
src/globalsearch/lastfmsearchprovider.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* 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 "searchprovider.h"
|
||||||
|
|
||||||
|
class LastFMService;
|
||||||
|
|
||||||
|
class LastFMSearchProvider : public BlockingSearchProvider {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
LastFMSearchProvider(LastFMService* service, QObject* parent);
|
||||||
|
|
||||||
|
static const int kResultLimit;
|
||||||
|
|
||||||
|
void LoadArtAsync(int id, const Result& result);
|
||||||
|
void LoadTracksAsync(int id, const Result& result);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ResultList Search(int id, const QString& query);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void RecreateItems();
|
||||||
|
|
||||||
|
private:
|
||||||
|
LastFMService* service_;
|
||||||
|
|
||||||
|
QImage icon_;
|
||||||
|
|
||||||
|
struct Item {
|
||||||
|
QString keyword_;
|
||||||
|
Song metadata_;
|
||||||
|
};
|
||||||
|
|
||||||
|
QMutex items_mutex_;
|
||||||
|
QList<Item> items_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LASTFMSEARCHPROVIDER_H
|
@ -136,7 +136,7 @@ void LibrarySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
|||||||
ret << result.metadata_;
|
ret << result.metadata_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Result::Type_Album: {
|
case Result::Type_Album: {
|
||||||
// Find all the songs in this album.
|
// Find all the songs in this album.
|
||||||
LibraryQuery query;
|
LibraryQuery query;
|
||||||
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
||||||
@ -156,6 +156,9 @@ void LibrarySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
|||||||
ret << song;
|
ret << song;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SortSongs(&ret);
|
SortSongs(&ret);
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
// The order of types here is the order they'll appear in the UI.
|
// The order of types here is the order they'll appear in the UI.
|
||||||
enum Type {
|
enum Type {
|
||||||
Type_Track = 0,
|
Type_Track = 0,
|
||||||
|
Type_Stream,
|
||||||
Type_Album
|
Type_Album
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,7 +114,7 @@ protected:
|
|||||||
// Sorts a list of songs by disc, then by track.
|
// Sorts a list of songs by disc, then by track.
|
||||||
static void SortSongs(SongList* list);
|
static void SortSongs(SongList* list);
|
||||||
|
|
||||||
// Subclasses must call this from their constructor
|
// Subclasses must call this from their constructors.
|
||||||
void Init(const QString& name, const QString& id, const QIcon& icon,
|
void Init(const QString& name, const QString& id, const QIcon& icon,
|
||||||
bool delay_searches, bool serialised_art);
|
bool delay_searches, bool serialised_art);
|
||||||
|
|
||||||
|
@ -166,6 +166,9 @@ void SpotifySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
|||||||
s->AlbumBrowse(uri);
|
s->AlbumBrowse(uri);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ QSize TooltipResultWidget::CalculateSizeHint() const {
|
|||||||
|
|
||||||
switch (result_.type_) {
|
switch (result_.type_) {
|
||||||
case SearchProvider::Result::Type_Track:
|
case SearchProvider::Result::Type_Track:
|
||||||
|
case SearchProvider::Result::Type_Stream:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SearchProvider::Result::Type_Album:
|
case SearchProvider::Result::Type_Album:
|
||||||
@ -119,6 +120,7 @@ void TooltipResultWidget::paintEvent(QPaintEvent*) {
|
|||||||
|
|
||||||
switch (result_.type_) {
|
switch (result_.type_) {
|
||||||
case SearchProvider::Result::Type_Track:
|
case SearchProvider::Result::Type_Track:
|
||||||
|
case SearchProvider::Result::Type_Stream:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SearchProvider::Result::Type_Album:
|
case SearchProvider::Result::Type_Album:
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include "lastfmurlhandler.h"
|
#include "lastfmurlhandler.h"
|
||||||
#include "internetmodel.h"
|
#include "internetmodel.h"
|
||||||
#include "internetplaylistitem.h"
|
#include "internetplaylistitem.h"
|
||||||
|
#include "globalsearch/globalsearch.h"
|
||||||
|
#include "globalsearch/lastfmsearchprovider.h"
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "core/player.h"
|
#include "core/player.h"
|
||||||
#include "core/song.h"
|
#include "core/song.h"
|
||||||
@ -79,6 +81,7 @@ LastFMService::LastFMService(InternetModel* parent)
|
|||||||
initial_tune_(false),
|
initial_tune_(false),
|
||||||
tune_task_id_(0),
|
tune_task_id_(0),
|
||||||
scrobbling_enabled_(false),
|
scrobbling_enabled_(false),
|
||||||
|
root_item_(NULL),
|
||||||
artist_list_(NULL),
|
artist_list_(NULL),
|
||||||
tag_list_(NULL),
|
tag_list_(NULL),
|
||||||
custom_list_(NULL),
|
custom_list_(NULL),
|
||||||
@ -111,6 +114,8 @@ LastFMService::LastFMService(InternetModel* parent)
|
|||||||
|
|
||||||
model()->player()->RegisterUrlHandler(url_handler_);
|
model()->player()->RegisterUrlHandler(url_handler_);
|
||||||
model()->cover_providers()->AddProvider(new LastFmCoverProvider(this));
|
model()->cover_providers()->AddProvider(new LastFmCoverProvider(this));
|
||||||
|
|
||||||
|
model()->global_search()->AddProvider(new LastFMSearchProvider(this, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
LastFMService::~LastFMService() {
|
LastFMService::~LastFMService() {
|
||||||
@ -126,8 +131,8 @@ void LastFMService::ReloadSettings() {
|
|||||||
buttons_visible_ = settings.value("ShowLoveBanButtons", true).toBool();
|
buttons_visible_ = settings.value("ShowLoveBanButtons", true).toBool();
|
||||||
scrobble_button_visible_ = settings.value("ShowScrobbleButton", true).toBool();
|
scrobble_button_visible_ = settings.value("ShowScrobbleButton", true).toBool();
|
||||||
|
|
||||||
friend_names_ = settings.value("FriendNames").toStringList();
|
|
||||||
last_refreshed_friends_ = settings.value("LastRefreshedFriends").toDateTime();
|
last_refreshed_friends_ = settings.value("LastRefreshedFriends").toDateTime();
|
||||||
|
friend_names_ = settings.value("FriendNames").toStringList();
|
||||||
|
|
||||||
//avoid emitting signal if it's not changed
|
//avoid emitting signal if it's not changed
|
||||||
if(scrobbling_enabled_old != scrobbling_enabled_)
|
if(scrobbling_enabled_old != scrobbling_enabled_)
|
||||||
@ -151,9 +156,9 @@ bool LastFMService::IsSubscriber() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QStandardItem* LastFMService::CreateRootItem() {
|
QStandardItem* LastFMService::CreateRootItem() {
|
||||||
QStandardItem* item = new QStandardItem(QIcon(":last.fm/as.png"), kServiceName);
|
root_item_ = new QStandardItem(QIcon(":last.fm/as.png"), kServiceName);
|
||||||
item->setData(true, InternetModel::Role_CanLazyLoad);
|
root_item_->setData(true, InternetModel::Role_CanLazyLoad);
|
||||||
return item;
|
return root_item_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastFMService::LazyPopulate(QStandardItem* parent) {
|
void LastFMService::LazyPopulate(QStandardItem* parent) {
|
||||||
@ -281,6 +286,7 @@ void LastFMService::SignOut() {
|
|||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.beginGroup(kSettingsGroup);
|
settings.beginGroup(kSettingsGroup);
|
||||||
|
|
||||||
settings.setValue("Username", QString());
|
settings.setValue("Username", QString());
|
||||||
settings.setValue("Session", QString());
|
settings.setValue("Session", QString());
|
||||||
settings.setValue("FriendNames", friend_names_);
|
settings.setValue("FriendNames", friend_names_);
|
||||||
@ -589,13 +595,55 @@ bool LastFMService::IsFriendsListStale() const {
|
|||||||
kFriendsCacheDurationSecs;
|
kFriendsCacheDurationSecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList LastFMService::FriendNames() {
|
||||||
|
// Update the list for next time, in the main thread.
|
||||||
|
if (IsFriendsListStale())
|
||||||
|
metaObject()->invokeMethod(this, "RefreshFriends", Qt::QueuedConnection);
|
||||||
|
|
||||||
|
QSettings s;
|
||||||
|
s.beginGroup(LastFMService::kSettingsGroup);
|
||||||
|
return s.value("FriendNames").toStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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() {
|
void LastFMService::ForceRefreshFriends() {
|
||||||
RefreshFriends(true);
|
RefreshFriends(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastFMService::RefreshFriends(bool force) {
|
void LastFMService::RefreshFriends(bool force) {
|
||||||
if (!friends_list_ || !IsAuthenticated())
|
if (!IsAuthenticated()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!friends_list_) {
|
||||||
|
root_item_->setData(false, InternetModel::Role_CanLazyLoad);
|
||||||
|
LazyPopulate(root_item_);
|
||||||
|
}
|
||||||
|
|
||||||
if (!force && !IsFriendsListStale()) {
|
if (!force && !IsFriendsListStale()) {
|
||||||
PopulateFriendsList();
|
PopulateFriendsList();
|
||||||
@ -635,6 +683,7 @@ void LastFMService::RefreshFriendsFinished() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
last_refreshed_friends_ = QDateTime::currentDateTime();
|
last_refreshed_friends_ = QDateTime::currentDateTime();
|
||||||
|
|
||||||
friend_names_ = QStringList();
|
friend_names_ = QStringList();
|
||||||
foreach (const lastfm::User& f, friends) {
|
foreach (const lastfm::User& f, friends) {
|
||||||
friend_names_ << f.name();
|
friend_names_ << f.name();
|
||||||
@ -646,6 +695,8 @@ void LastFMService::RefreshFriendsFinished() {
|
|||||||
s.setValue("LastRefreshedFriends", last_refreshed_friends_);
|
s.setValue("LastRefreshedFriends", last_refreshed_friends_);
|
||||||
|
|
||||||
PopulateFriendsList();
|
PopulateFriendsList();
|
||||||
|
|
||||||
|
emit SavedItemsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastFMService::PopulateFriendsList() {
|
void LastFMService::PopulateFriendsList() {
|
||||||
@ -756,6 +807,8 @@ void LastFMService::AddArtistOrTag(const QString& name,
|
|||||||
emit AddItemToPlaylist(item->index(), AddMode_Append);
|
emit AddItemToPlaylist(item->index(), AddMode_Append);
|
||||||
|
|
||||||
SaveList(name, list);
|
SaveList(name, list);
|
||||||
|
|
||||||
|
emit SavedItemsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastFMService::SaveList(const QString& name, QStandardItem* list) const {
|
void LastFMService::SaveList(const QString& name, QStandardItem* list) const {
|
||||||
@ -774,35 +827,30 @@ void LastFMService::RestoreList(const QString& name,
|
|||||||
const QString& url_pattern,
|
const QString& url_pattern,
|
||||||
const QString& title_pattern,
|
const QString& title_pattern,
|
||||||
const QIcon& icon, QStandardItem* parent) {
|
const QIcon& icon, QStandardItem* parent) {
|
||||||
QSettings settings;
|
|
||||||
settings.beginGroup(kSettingsGroup);
|
|
||||||
|
|
||||||
if (parent->hasChildren())
|
if (parent->hasChildren())
|
||||||
parent->removeRows(0, parent->rowCount());
|
parent->removeRows(0, parent->rowCount());
|
||||||
|
|
||||||
int count = settings.beginReadArray(name);
|
const QStringList keys = SavedArtistOrTagRadioNames(name);
|
||||||
for (int i=0 ; i<count ; ++i) {
|
|
||||||
settings.setArrayIndex(i);
|
foreach (const QString& key, keys) {
|
||||||
QString content = settings.value("key").toString();
|
|
||||||
QString url;
|
QString url;
|
||||||
if (name == "custom" && content.startsWith("lastfm://")) {
|
if (name == "custom" && key.startsWith("lastfm://")) {
|
||||||
url = content;
|
url = key;
|
||||||
} else if (name == "custom") {
|
} else if (name == "custom") {
|
||||||
url = url_pattern.arg(QString(content.toUtf8().toBase64()));
|
url = url_pattern.arg(QString(key.toUtf8().toBase64()));
|
||||||
} else {
|
} else {
|
||||||
url = url_pattern.arg(content);
|
url = url_pattern.arg(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Song song;
|
Song song;
|
||||||
song.set_url(QUrl(url));
|
song.set_url(QUrl(url));
|
||||||
song.set_title(title_pattern.arg(content));
|
song.set_title(title_pattern.arg(key));
|
||||||
|
|
||||||
QStandardItem* item = new QStandardItem(icon, content);
|
QStandardItem* item = new QStandardItem(icon, key);
|
||||||
item->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata);
|
item->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata);
|
||||||
item->setData(InternetModel::PlayBehaviour_SingleItem, InternetModel::Role_PlayBehaviour);
|
item->setData(InternetModel::PlayBehaviour_SingleItem, InternetModel::Role_PlayBehaviour);
|
||||||
parent->appendRow(item);
|
parent->appendRow(item);
|
||||||
}
|
}
|
||||||
settings.endArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastFMService::Remove() {
|
void LastFMService::Remove() {
|
||||||
|
@ -113,6 +113,11 @@ class LastFMService : public InternetService {
|
|||||||
|
|
||||||
bool IsFriendsListStale() const;
|
bool IsFriendsListStale() const;
|
||||||
|
|
||||||
|
// Thread safe
|
||||||
|
QStringList FriendNames();
|
||||||
|
QStringList SavedArtistRadioNames() const;
|
||||||
|
QStringList SavedTagRadioNames() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void NowPlaying(const Song& song);
|
void NowPlaying(const Song& song);
|
||||||
void Scrobble();
|
void Scrobble();
|
||||||
@ -130,6 +135,8 @@ class LastFMService : public InternetService {
|
|||||||
void UpdatedSubscriberStatus(bool is_subscriber);
|
void UpdatedSubscriberStatus(bool is_subscriber);
|
||||||
void ScrobbledRadioStream();
|
void ScrobbledRadioStream();
|
||||||
|
|
||||||
|
void SavedItemsChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QModelIndex GetCurrentIndex();
|
QModelIndex GetCurrentIndex();
|
||||||
|
|
||||||
@ -146,6 +153,7 @@ class LastFMService : public InternetService {
|
|||||||
void AddTagRadio();
|
void AddTagRadio();
|
||||||
void AddCustomRadio();
|
void AddCustomRadio();
|
||||||
void ForceRefreshFriends();
|
void ForceRefreshFriends();
|
||||||
|
void RefreshFriends();
|
||||||
void Remove();
|
void Remove();
|
||||||
|
|
||||||
// Radio tuner.
|
// Radio tuner.
|
||||||
@ -208,6 +216,7 @@ class LastFMService : public InternetService {
|
|||||||
bool buttons_visible_;
|
bool buttons_visible_;
|
||||||
bool scrobble_button_visible_;
|
bool scrobble_button_visible_;
|
||||||
|
|
||||||
|
QStandardItem* root_item_;
|
||||||
QStandardItem* artist_list_;
|
QStandardItem* artist_list_;
|
||||||
QStandardItem* tag_list_;
|
QStandardItem* tag_list_;
|
||||||
QStandardItem* custom_list_;
|
QStandardItem* custom_list_;
|
||||||
|
@ -220,6 +220,7 @@ int main(int argc, char *argv[]) {
|
|||||||
qRegisterMetaTypeStreamOperators<QMap<int, int> >("ColumnAlignmentMap");
|
qRegisterMetaTypeStreamOperators<QMap<int, int> >("ColumnAlignmentMap");
|
||||||
qRegisterMetaType<QNetworkCookie>("QNetworkCookie");
|
qRegisterMetaType<QNetworkCookie>("QNetworkCookie");
|
||||||
qRegisterMetaType<QList<QNetworkCookie> >("QList<QNetworkCookie>");
|
qRegisterMetaType<QList<QNetworkCookie> >("QList<QNetworkCookie>");
|
||||||
|
qRegisterMetaType<SearchProvider::ResultList>("SearchProvider::ResultList");
|
||||||
|
|
||||||
qRegisterMetaType<GstBuffer*>("GstBuffer*");
|
qRegisterMetaType<GstBuffer*>("GstBuffer*");
|
||||||
qRegisterMetaType<GstElement*>("GstElement*");
|
qRegisterMetaType<GstElement*>("GstElement*");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user