Play last.fm tag radio or similar artists radio when clicking on a tag in the song/artist info pane.
This commit is contained in:
parent
a41b6de040
commit
b97b2138fa
@ -65,7 +65,7 @@ class Player : public QObject {
|
||||
Engine::State GetState() const;
|
||||
int GetVolume() const;
|
||||
|
||||
boost::shared_ptr<PlaylistItem> GetCurrentItem() const { return current_item_; }
|
||||
PlaylistItemPtr GetCurrentItem() const { return current_item_; }
|
||||
|
||||
// MPRIS
|
||||
enum DBusCaps {
|
||||
@ -175,7 +175,7 @@ class Player : public QObject {
|
||||
LastFMService* lastfm_;
|
||||
QSettings settings_;
|
||||
|
||||
boost::shared_ptr<PlaylistItem> current_item_;
|
||||
PlaylistItemPtr current_item_;
|
||||
|
||||
boost::scoped_ptr<EngineBase> engine_;
|
||||
Engine::TrackChangeType stream_change_type_;
|
||||
|
@ -673,7 +673,7 @@ QModelIndex Playlist::InsertItemsWithoutUndo(const PlaylistItemList& items,
|
||||
|
||||
beginInsertRows(QModelIndex(), start, end);
|
||||
for (int i=start ; i<=end ; ++i) {
|
||||
boost::shared_ptr<PlaylistItem> item = items[i - start];
|
||||
PlaylistItemPtr item = items[i - start];
|
||||
items_.insert(i, item);
|
||||
virtual_items_ << virtual_items_.count();
|
||||
|
||||
@ -948,7 +948,7 @@ PlaylistItemList Playlist::RemoveItemsWithoutUndo(int row, int count) {
|
||||
// Remove items
|
||||
PlaylistItemList ret;
|
||||
for (int i=0 ; i<count ; ++i) {
|
||||
boost::shared_ptr<PlaylistItem> item(items_.takeAt(row));
|
||||
PlaylistItemPtr item(items_.takeAt(row));
|
||||
ret << item;
|
||||
|
||||
if (item->type() == "Library") {
|
||||
@ -1118,7 +1118,7 @@ QSortFilterProxyModel* Playlist::proxy() const {
|
||||
|
||||
SongList Playlist::GetAllSongs() const {
|
||||
SongList ret;
|
||||
foreach (boost::shared_ptr<PlaylistItem> item, items_) {
|
||||
foreach (PlaylistItemPtr item, items_) {
|
||||
ret << item->Metadata();
|
||||
}
|
||||
return ret;
|
||||
@ -1126,7 +1126,7 @@ SongList Playlist::GetAllSongs() const {
|
||||
|
||||
quint64 Playlist::GetTotalLength() const {
|
||||
quint64 ret = 0;
|
||||
foreach (boost::shared_ptr<PlaylistItem> item, items_) {
|
||||
foreach (PlaylistItemPtr item, items_) {
|
||||
int length = item->Metadata().length();
|
||||
if (length > 0)
|
||||
ret += length;
|
||||
|
@ -94,8 +94,7 @@ class Playlist : public QAbstractListModel {
|
||||
static const char* kPlayNowMimetype;
|
||||
|
||||
static bool CompareItems(int column, Qt::SortOrder order,
|
||||
boost::shared_ptr<PlaylistItem> a,
|
||||
boost::shared_ptr<PlaylistItem> b);
|
||||
PlaylistItemPtr a, PlaylistItemPtr b);
|
||||
|
||||
static QString column_name(Column column);
|
||||
static bool column_is_editable(Playlist::Column column);
|
||||
@ -116,8 +115,8 @@ class Playlist : public QAbstractListModel {
|
||||
int previous_index() const;
|
||||
bool stop_after_current() const;
|
||||
|
||||
const boost::shared_ptr<PlaylistItem>& item_at(int index) const { return items_[index]; }
|
||||
boost::shared_ptr<PlaylistItem> current_item() const { return current_item_; }
|
||||
const PlaylistItemPtr& item_at(int index) const { return items_[index]; }
|
||||
PlaylistItemPtr current_item() const { return current_item_; }
|
||||
|
||||
PlaylistItem::Options current_item_options() const;
|
||||
Song current_item_metadata() const;
|
||||
@ -226,7 +225,7 @@ class Playlist : public QAbstractListModel {
|
||||
// that they will be played.
|
||||
// A map of library ID to playlist item - for fast lookups when library
|
||||
// items change.
|
||||
QMultiMap<int, boost::shared_ptr<PlaylistItem> > library_items_by_id_;
|
||||
QMultiMap<int, PlaylistItemPtr> library_items_by_id_;
|
||||
|
||||
QPersistentModelIndex current_item_index_;
|
||||
QPersistentModelIndex last_played_item_index_;
|
||||
@ -234,7 +233,7 @@ class Playlist : public QAbstractListModel {
|
||||
bool current_is_paused_;
|
||||
int current_virtual_index_;
|
||||
|
||||
boost::shared_ptr<PlaylistItem> current_item_;
|
||||
PlaylistItemPtr current_item_;
|
||||
|
||||
bool is_shuffled_;
|
||||
|
||||
|
@ -40,7 +40,7 @@ class PlaylistBackend : public QObject {
|
||||
int last_played;
|
||||
};
|
||||
typedef QList<Playlist> PlaylistList;
|
||||
typedef QFuture<boost::shared_ptr<PlaylistItem> > PlaylistItemFuture;
|
||||
typedef QFuture<PlaylistItemPtr> PlaylistItemFuture;
|
||||
|
||||
PlaylistList GetAllPlaylists();
|
||||
Playlist GetPlaylist(int id);
|
||||
@ -57,7 +57,7 @@ class PlaylistBackend : public QObject {
|
||||
void SavePlaylist(int playlist, const PlaylistItemList& items, int last_played);
|
||||
|
||||
private:
|
||||
static boost::shared_ptr<PlaylistItem> NewSongFromQuery(const SqlRow& row);
|
||||
static PlaylistItemPtr NewSongFromQuery(const SqlRow& row);
|
||||
|
||||
boost::shared_ptr<Database> db_;
|
||||
};
|
||||
|
@ -63,7 +63,7 @@ void PlaylistItem::ClearTemporaryMetadata() {
|
||||
temp_metadata_ = Song();
|
||||
}
|
||||
|
||||
static void ReloadPlaylistItem(boost::shared_ptr<PlaylistItem> item) {
|
||||
static void ReloadPlaylistItem(PlaylistItemPtr item) {
|
||||
item->Reload();
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,8 @@ class PlaylistItem : public boost::enable_shared_from_this<PlaylistItem> {
|
||||
|
||||
Song temp_metadata_;
|
||||
};
|
||||
typedef QList<boost::shared_ptr<PlaylistItem> > PlaylistItemList;
|
||||
typedef boost::shared_ptr<PlaylistItem> PlaylistItemPtr;
|
||||
typedef QList<PlaylistItemPtr> PlaylistItemList;
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(PlaylistItem::Options);
|
||||
|
||||
|
@ -263,7 +263,7 @@ void PlaylistManager::SongsDiscovered(const SongList& songs) {
|
||||
foreach (const Song& song, songs) {
|
||||
foreach (const Data& data, playlists_) {
|
||||
PlaylistItemList items = data.p->library_items_by_id(song.id());
|
||||
foreach (boost::shared_ptr<PlaylistItem> item, items) {
|
||||
foreach (PlaylistItemPtr item, items) {
|
||||
if (item->Metadata().directory_id() != song.directory_id())
|
||||
continue;
|
||||
static_cast<LibraryPlaylistItem*>(item.get())->SetMetadata(song);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "radioitem.h"
|
||||
#include "lastfmstationdialog.h"
|
||||
#include "radiomodel.h"
|
||||
#include "radioplaylistitem.h"
|
||||
#include "core/networkaccessmanager.h"
|
||||
#include "core/song.h"
|
||||
#include "core/taskmanager.h"
|
||||
@ -725,3 +726,25 @@ PlaylistItem::Options LastFMService::playlistitem_options() const {
|
||||
PlaylistItem::PauseDisabled |
|
||||
PlaylistItem::ContainsMultipleTracks;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
PlaylistItemPtr ret;
|
||||
|
||||
if (url.scheme() != "lastfm")
|
||||
return ret;
|
||||
|
||||
QStringList sections(url.path().split("/", QString::SkipEmptyParts));
|
||||
|
||||
if (sections.count() == 2 && url.host() == "artist" && sections[1] == "similarartists") {
|
||||
ret.reset(new RadioPlaylistItem(this, url,
|
||||
tr("Last.fm Similar Artists to %1").arg(sections[0]), QString()));
|
||||
} else if (sections.count() == 1 && url.host() == "globaltags") {
|
||||
ret.reset(new RadioPlaylistItem(this, url,
|
||||
tr("Last.fm Tag Radio: %1").arg(sections[0]), QString()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ uint qHash(const lastfm::Track& track);
|
||||
#include "radioservice.h"
|
||||
#include "lastfmstationdialog.h"
|
||||
#include "core/song.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QMenu>
|
||||
@ -104,11 +105,14 @@ class LastFMService : public RadioService {
|
||||
|
||||
void FetchMoreTracks();
|
||||
|
||||
PlaylistItemPtr PlaylistItemForUrl(const QUrl& url);
|
||||
|
||||
public slots:
|
||||
void NowPlaying(const Song& song);
|
||||
void Scrobble();
|
||||
void Love();
|
||||
void Ban();
|
||||
void ShowConfig();
|
||||
|
||||
signals:
|
||||
void AuthenticationComplete(bool success);
|
||||
@ -119,7 +123,6 @@ class LastFMService : public RadioService {
|
||||
void AuthenticateReplyFinished();
|
||||
void RefreshFriendsFinished();
|
||||
void RefreshNeighboursFinished();
|
||||
void ShowConfig();
|
||||
|
||||
void TunerTrackAvailable();
|
||||
void TunerError(lastfm::ws::Error error);
|
||||
|
@ -212,4 +212,8 @@ void SongInfoBase::ConnectWidget(QWidget* widget) {
|
||||
if (widget->metaObject()->indexOfSignal("ShowSettingsDialog()") != -1) {
|
||||
connect(widget, SIGNAL(ShowSettingsDialog()), SIGNAL(ShowSettingsDialog()));
|
||||
}
|
||||
|
||||
if (widget->metaObject()->indexOfSignal("AddPlaylistItems(PlaylistItemList)") != -1) {
|
||||
connect(widget, SIGNAL(AddPlaylistItems(PlaylistItemList)), SIGNAL(AddPlaylistItems(PlaylistItemList)));
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "collapsibleinfopane.h"
|
||||
#include "songinfofetcher.h"
|
||||
#include "core/song.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "widgets/widgetfadehelper.h"
|
||||
|
||||
class CollapsibleInfoPane;
|
||||
@ -46,6 +47,7 @@ public slots:
|
||||
|
||||
signals:
|
||||
void ShowSettingsDialog();
|
||||
void AddPlaylistItems(const PlaylistItemList& items);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent* e);
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
|
||||
#include "tagwidget.h"
|
||||
#include "radio/lastfmservice.h"
|
||||
#include "radio/radiomodel.h"
|
||||
#include "ui/flowlayout.h"
|
||||
|
||||
#include <QPainter>
|
||||
@ -93,6 +95,10 @@ void TagWidgetTag::paintEvent(QPaintEvent*) {
|
||||
p.drawText(text_rect, text_);
|
||||
}
|
||||
|
||||
void TagWidgetTag::mouseReleaseEvent(QMouseEvent*) {
|
||||
emit Clicked();
|
||||
}
|
||||
|
||||
|
||||
TagWidget::TagWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
@ -105,6 +111,27 @@ void TagWidget::AddTag(const QString& tag) {
|
||||
return;
|
||||
|
||||
TagWidgetTag* widget = new TagWidgetTag(icon_, tag, this);
|
||||
connect(widget, SIGNAL(Clicked()), SLOT(TagClicked()));
|
||||
|
||||
layout()->addWidget(widget);
|
||||
tags_ << widget;
|
||||
}
|
||||
|
||||
void TagWidget::TagClicked() {
|
||||
TagWidgetTag* tag = qobject_cast<TagWidgetTag*>(sender());
|
||||
if (!tag)
|
||||
return;
|
||||
|
||||
LastFMService* last_fm = RadioModel::Service<LastFMService>();
|
||||
if (!last_fm->IsAuthenticated()) {
|
||||
last_fm->ShowConfig();
|
||||
return;
|
||||
}
|
||||
|
||||
QUrl url(url_pattern_.arg(tag->text()));
|
||||
PlaylistItemPtr item(last_fm->PlaylistItemForUrl(url));
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
emit AddPlaylistItems(PlaylistItemList() << item);
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef TAGWIDGET_H
|
||||
#define TAGWIDGET_H
|
||||
|
||||
#include "playlist/playlistitem.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QWidget>
|
||||
|
||||
@ -40,11 +42,16 @@ public:
|
||||
void set_background_opacity(float opacity);
|
||||
|
||||
QSize sizeHint() const;
|
||||
QString text() const { return text_; }
|
||||
|
||||
signals:
|
||||
void Clicked();
|
||||
|
||||
protected:
|
||||
void enterEvent(QEvent*);
|
||||
void leaveEvent(QEvent*);
|
||||
void paintEvent(QPaintEvent*);
|
||||
void mouseReleaseEvent(QMouseEvent*);
|
||||
|
||||
private:
|
||||
QString text_;
|
||||
@ -66,6 +73,12 @@ public:
|
||||
|
||||
int count() const { return tags_.count(); }
|
||||
|
||||
signals:
|
||||
void AddPlaylistItems(const PlaylistItemList& items);
|
||||
|
||||
private slots:
|
||||
void TagClicked();
|
||||
|
||||
private:
|
||||
QString url_pattern_;
|
||||
QIcon icon_;
|
||||
|
@ -1596,6 +1596,7 @@ void MainWindow::ConnectInfoView(SongInfoBase* view) {
|
||||
connect(player_, SIGNAL(Stopped()), view, SLOT(SongFinished()));
|
||||
|
||||
connect(view, SIGNAL(ShowSettingsDialog()), SLOT(ShowSongInfoConfig()));
|
||||
connect(view, SIGNAL(AddPlaylistItems(PlaylistItemList)), SLOT(InsertRadioItems(PlaylistItemList)));
|
||||
}
|
||||
|
||||
void MainWindow::ShowSongInfoConfig() {
|
||||
|
@ -440,7 +440,7 @@ TEST_F(PlaylistTest, LibraryIdMapSingle) {
|
||||
song.Init("title", "artist", "album", 123);
|
||||
song.set_id(1);
|
||||
|
||||
boost::shared_ptr<PlaylistItem> item(new LibraryPlaylistItem(song));
|
||||
PlaylistItemPtr item(new LibraryPlaylistItem(song));
|
||||
playlist_.InsertItems(PlaylistItemList() << item);
|
||||
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(-1).count());
|
||||
@ -459,7 +459,7 @@ TEST_F(PlaylistTest, LibraryIdMapInvalid) {
|
||||
invalid.Init("title", "artist", "album", 123);
|
||||
ASSERT_EQ(-1, invalid.id());
|
||||
|
||||
boost::shared_ptr<PlaylistItem> item(new LibraryPlaylistItem(invalid));
|
||||
PlaylistItemPtr item(new LibraryPlaylistItem(invalid));
|
||||
playlist_.InsertItems(PlaylistItemList() << item);
|
||||
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(-1).count());
|
||||
@ -477,9 +477,9 @@ TEST_F(PlaylistTest, LibraryIdMapMulti) {
|
||||
two.Init("title 2", "artist 2", "album 2", 123);
|
||||
two.set_id(2);
|
||||
|
||||
boost::shared_ptr<PlaylistItem> item_one(new LibraryPlaylistItem(one));
|
||||
boost::shared_ptr<PlaylistItem> item_two(new LibraryPlaylistItem(two));
|
||||
boost::shared_ptr<PlaylistItem> item_three(new LibraryPlaylistItem(one));
|
||||
PlaylistItemPtr item_one(new LibraryPlaylistItem(one));
|
||||
PlaylistItemPtr item_two(new LibraryPlaylistItem(two));
|
||||
PlaylistItemPtr item_three(new LibraryPlaylistItem(one));
|
||||
playlist_.InsertItems(PlaylistItemList() << item_one << item_two << item_three);
|
||||
|
||||
EXPECT_EQ(2, playlist_.library_items_by_id(1).count());
|
||||
|
Loading…
x
Reference in New Issue
Block a user