Tag and artist radio
This commit is contained in:
parent
bfc81e4d5c
commit
efefc35d6e
4
TODO
4
TODO
|
@ -8,10 +8,6 @@
|
||||||
- Make QSortFilterProxyModel on the library obey hasChildren()
|
- Make QSortFilterProxyModel on the library obey hasChildren()
|
||||||
- More columns in playlist
|
- More columns in playlist
|
||||||
|
|
||||||
Last.fm:
|
|
||||||
- Artist/tag/etc. radio
|
|
||||||
- More types of radio
|
|
||||||
|
|
||||||
Long-term:
|
Long-term:
|
||||||
- iPod
|
- iPod
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "lastfmconfig.h"
|
#include "lastfmconfig.h"
|
||||||
#include "radioitem.h"
|
#include "radioitem.h"
|
||||||
#include "song.h"
|
#include "song.h"
|
||||||
|
#include "lastfmstationdialog.h"
|
||||||
|
|
||||||
#include <lastfm/ws.h>
|
#include <lastfm/ws.h>
|
||||||
#include <lastfm/misc.h>
|
#include <lastfm/misc.h>
|
||||||
|
@ -21,9 +22,12 @@ LastFMService::LastFMService(QObject* parent)
|
||||||
: RadioService(kServiceName, parent),
|
: RadioService(kServiceName, parent),
|
||||||
tuner_(NULL),
|
tuner_(NULL),
|
||||||
scrobbler_(NULL),
|
scrobbler_(NULL),
|
||||||
|
station_dialog_(new LastFMStationDialog),
|
||||||
context_menu_(new QMenu),
|
context_menu_(new QMenu),
|
||||||
initial_tune_(false),
|
initial_tune_(false),
|
||||||
scrobbling_enabled_(false),
|
scrobbling_enabled_(false),
|
||||||
|
artist_list_(NULL),
|
||||||
|
tag_list_(NULL),
|
||||||
friends_list_(NULL),
|
friends_list_(NULL),
|
||||||
neighbours_list_(NULL)
|
neighbours_list_(NULL)
|
||||||
{
|
{
|
||||||
|
@ -44,13 +48,18 @@ LastFMService::LastFMService(QObject* parent)
|
||||||
|
|
||||||
play_action_ = context_menu_->addAction(QIcon(":media-playback-start.png"), "Add to playlist", this, SLOT(AddToPlaylist()));
|
play_action_ = context_menu_->addAction(QIcon(":media-playback-start.png"), "Add to playlist", this, SLOT(AddToPlaylist()));
|
||||||
context_menu_->addSeparator();
|
context_menu_->addSeparator();
|
||||||
|
add_artist_action_ = context_menu_->addAction(QIcon(":last.fm/icon_radio.png"), "Play artist radio...", this, SLOT(AddArtistRadio()));
|
||||||
|
add_tag_action_ = context_menu_->addAction(QIcon(":last.fm/icon_tag.png"), "Play tag radio...", this, SLOT(AddTagRadio()));
|
||||||
context_menu_->addAction(QIcon(":configure.png"), "Configure Last.fm...",
|
context_menu_->addAction(QIcon(":configure.png"), "Configure Last.fm...",
|
||||||
config_, SLOT(show()));
|
config_, SLOT(show()));
|
||||||
|
|
||||||
|
add_artist_action_->setEnabled(false);
|
||||||
|
add_tag_action_->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
LastFMService::~LastFMService() {
|
LastFMService::~LastFMService() {
|
||||||
delete config_;
|
delete config_;
|
||||||
|
delete station_dialog_;
|
||||||
delete context_menu_;
|
delete context_menu_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +84,6 @@ RadioItem* LastFMService::CreateRootItem(RadioItem* parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastFMService::LazyPopulate(RadioItem *item) {
|
void LastFMService::LazyPopulate(RadioItem *item) {
|
||||||
RadioItem* c = NULL;
|
|
||||||
|
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
case RadioItem::Type_Service:
|
case RadioItem::Type_Service:
|
||||||
// Normal radio types
|
// Normal radio types
|
||||||
|
@ -85,16 +92,18 @@ void LastFMService::LazyPopulate(RadioItem *item) {
|
||||||
CreateStationItem(Type_MyLoved, "My Loved Tracks", ":last.fm/loved_radio.png", item);
|
CreateStationItem(Type_MyLoved, "My Loved Tracks", ":last.fm/loved_radio.png", item);
|
||||||
CreateStationItem(Type_MyNeighbourhood, "My Neighbourhood", ":last.fm/neighbour_radio.png", item);
|
CreateStationItem(Type_MyNeighbourhood, "My Neighbourhood", ":last.fm/neighbour_radio.png", item);
|
||||||
|
|
||||||
// Types that spawn a popup dialog
|
|
||||||
c = CreateStationItem(Type_ArtistRadio, "Artist radio...",
|
|
||||||
":last.fm/icon_radio.png", item);
|
|
||||||
c->playable = false;
|
|
||||||
|
|
||||||
c = CreateStationItem(Type_TagRadio, "Tag radio...",
|
|
||||||
":last.fm/icon_tag.png", item);
|
|
||||||
c->playable = false;
|
|
||||||
|
|
||||||
// Types that have children
|
// Types that have children
|
||||||
|
artist_list_ = new RadioItem(this, Type_ArtistRadio, "Artist radio", item);
|
||||||
|
artist_list_->icon = QIcon(":last.fm/icon_radio.png");
|
||||||
|
artist_list_->lazy_loaded = true;
|
||||||
|
|
||||||
|
tag_list_ = new RadioItem(this, Type_TagRadio, "Tag radio", item);
|
||||||
|
tag_list_->icon = QIcon(":last.fm/icon_tag.png");
|
||||||
|
tag_list_->lazy_loaded = true;
|
||||||
|
|
||||||
|
RestoreList("artists", Type_Artist, QIcon(":last.fm/icon_radio.png"), artist_list_);
|
||||||
|
RestoreList("tags", Type_Tag, QIcon(":last.fm/icon_tag.png"), tag_list_);
|
||||||
|
|
||||||
friends_list_ = new RadioItem(this, Type_MyFriends, "Friends", item);
|
friends_list_ = new RadioItem(this, Type_MyFriends, "Friends", item);
|
||||||
friends_list_->icon = QIcon(":last.fm/my_friends.png");
|
friends_list_->icon = QIcon(":last.fm/my_friends.png");
|
||||||
|
|
||||||
|
@ -103,6 +112,9 @@ void LastFMService::LazyPopulate(RadioItem *item) {
|
||||||
|
|
||||||
if (!IsAuthenticated())
|
if (!IsAuthenticated())
|
||||||
config_->show();
|
config_->show();
|
||||||
|
|
||||||
|
add_artist_action_->setEnabled(true);
|
||||||
|
add_tag_action_->setEnabled(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_MyFriends:
|
case Type_MyFriends:
|
||||||
|
@ -204,6 +216,12 @@ QUrl LastFMService::UrlForItem(const RadioItem* item) const {
|
||||||
|
|
||||||
case Type_OtherUserNeighbourhood:
|
case Type_OtherUserNeighbourhood:
|
||||||
return "lastfm://user/" + item->key + "/neighbours";
|
return "lastfm://user/" + item->key + "/neighbours";
|
||||||
|
|
||||||
|
case Type_Artist:
|
||||||
|
return "lastfm://artist/" + item->key + "/similarartists";
|
||||||
|
|
||||||
|
case Type_Tag:
|
||||||
|
return "lastfm://globaltags/" + item->key;
|
||||||
}
|
}
|
||||||
return QUrl();
|
return QUrl();
|
||||||
}
|
}
|
||||||
|
@ -220,6 +238,8 @@ QString LastFMService::TitleForItem(const RadioItem* item) const {
|
||||||
case Type_OtherUserRadio: return item->key + "'s Library";
|
case Type_OtherUserRadio: return item->key + "'s Library";
|
||||||
case Type_OtherUserLoved: return item->key + "'s Loved Tracks";
|
case Type_OtherUserLoved: return item->key + "'s Loved Tracks";
|
||||||
case Type_OtherUserNeighbourhood: return item->key + "'s Neighbour Radio";
|
case Type_OtherUserNeighbourhood: return item->key + "'s Neighbour Radio";
|
||||||
|
case Type_Artist: return "Similar artists to " + item->key;
|
||||||
|
case Type_Tag: return "Tag radio: " + item->key;
|
||||||
}
|
}
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
@ -444,3 +464,62 @@ void LastFMService::RefreshNeighboursFinished() {
|
||||||
void LastFMService::AddToPlaylist() {
|
void LastFMService::AddToPlaylist() {
|
||||||
emit AddItemToPlaylist(context_item_);
|
emit AddItemToPlaylist(context_item_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LastFMService::AddArtistRadio() {
|
||||||
|
AddArtistOrTag("artists", LastFMStationDialog::Artist, Type_Artist, QIcon(":last.fm/icon_radio.png"), artist_list_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LastFMService::AddTagRadio() {
|
||||||
|
AddArtistOrTag("tags", LastFMStationDialog::Tag, Type_Tag, QIcon(":last.fm/icon_tag.png"), tag_list_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LastFMService::AddArtistOrTag(const QString& name,
|
||||||
|
LastFMStationDialog::Type dialog_type, ItemType item_type,
|
||||||
|
const QIcon& icon, RadioItem* list) {
|
||||||
|
station_dialog_->SetType(dialog_type);
|
||||||
|
if (station_dialog_->exec() == QDialog::Rejected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (station_dialog_->content().isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
RadioItem* item = new RadioItem(this, item_type, station_dialog_->content());
|
||||||
|
item->icon = icon;
|
||||||
|
item->playable = true;
|
||||||
|
item->lazy_loaded = true;
|
||||||
|
item->InsertNotify(list);
|
||||||
|
emit AddItemToPlaylist(item);
|
||||||
|
|
||||||
|
SaveList(name, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LastFMService::SaveList(const QString& name, RadioItem* list) const {
|
||||||
|
QSettings settings;
|
||||||
|
settings.beginGroup(kSettingsGroup);
|
||||||
|
|
||||||
|
settings.beginWriteArray(name, list->children.count());
|
||||||
|
for (int i=0 ; i<list->children.count() ; ++i) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
settings.setValue("key", list->children[i]->key);
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LastFMService::RestoreList(const QString &name, ItemType item_type,
|
||||||
|
const QIcon& icon, RadioItem *list) {
|
||||||
|
QSettings settings;
|
||||||
|
settings.beginGroup(kSettingsGroup);
|
||||||
|
|
||||||
|
list->ClearNotify();
|
||||||
|
|
||||||
|
int count = settings.beginReadArray(name);
|
||||||
|
for (int i=0 ; i<count ; ++i) {
|
||||||
|
settings.setArrayIndex(i);
|
||||||
|
RadioItem* item = new RadioItem(this, item_type,
|
||||||
|
settings.value("key").toString(), list);
|
||||||
|
item->icon = icon;
|
||||||
|
item->playable = true;
|
||||||
|
item->lazy_loaded = true;
|
||||||
|
}
|
||||||
|
settings.endArray();
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "radioservice.h"
|
#include "radioservice.h"
|
||||||
#include "song.h"
|
#include "song.h"
|
||||||
|
#include "lastfmstationdialog.h"
|
||||||
|
|
||||||
#include <lastfm/RadioTuner>
|
#include <lastfm/RadioTuner>
|
||||||
|
|
||||||
|
@ -37,6 +38,8 @@ class LastFMService : public RadioService {
|
||||||
Type_OtherUserRadio,
|
Type_OtherUserRadio,
|
||||||
Type_OtherUserLoved,
|
Type_OtherUserLoved,
|
||||||
Type_OtherUserNeighbourhood,
|
Type_OtherUserNeighbourhood,
|
||||||
|
Type_Artist,
|
||||||
|
Type_Tag,
|
||||||
};
|
};
|
||||||
|
|
||||||
// RadioService
|
// RadioService
|
||||||
|
@ -80,6 +83,8 @@ class LastFMService : public RadioService {
|
||||||
void TunerError(lastfm::ws::Error error);
|
void TunerError(lastfm::ws::Error error);
|
||||||
|
|
||||||
void AddToPlaylist();
|
void AddToPlaylist();
|
||||||
|
void AddArtistRadio();
|
||||||
|
void AddTagRadio();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RadioItem* CreateStationItem(ItemType type, const QString& name,
|
RadioItem* CreateStationItem(ItemType type, const QString& name,
|
||||||
|
@ -89,6 +94,12 @@ class LastFMService : public RadioService {
|
||||||
lastfm::Track TrackFromSong(const Song& song) const;
|
lastfm::Track TrackFromSong(const Song& song) const;
|
||||||
void RefreshFriends();
|
void RefreshFriends();
|
||||||
void RefreshNeighbours();
|
void RefreshNeighbours();
|
||||||
|
void AddArtistOrTag(const QString& name,
|
||||||
|
LastFMStationDialog::Type dialog_type, ItemType item_type,
|
||||||
|
const QIcon& icon, RadioItem* list);
|
||||||
|
void SaveList(const QString& name, RadioItem* list) const;
|
||||||
|
void RestoreList(const QString &name, ItemType item_type,
|
||||||
|
const QIcon& icon, RadioItem *list);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lastfm::RadioTuner* tuner_;
|
lastfm::RadioTuner* tuner_;
|
||||||
|
@ -96,9 +107,13 @@ class LastFMService : public RadioService {
|
||||||
lastfm::Track last_track_;
|
lastfm::Track last_track_;
|
||||||
|
|
||||||
LastFMConfig* config_;
|
LastFMConfig* config_;
|
||||||
|
LastFMStationDialog* station_dialog_;
|
||||||
|
|
||||||
QMenu* context_menu_;
|
QMenu* context_menu_;
|
||||||
QAction* play_action_;
|
QAction* play_action_;
|
||||||
|
QAction* remove_action_;
|
||||||
|
QAction* add_artist_action_;
|
||||||
|
QAction* add_tag_action_;
|
||||||
RadioItem* context_item_;
|
RadioItem* context_item_;
|
||||||
|
|
||||||
QUrl last_url_;
|
QUrl last_url_;
|
||||||
|
@ -106,6 +121,8 @@ class LastFMService : public RadioService {
|
||||||
|
|
||||||
bool scrobbling_enabled_;
|
bool scrobbling_enabled_;
|
||||||
|
|
||||||
|
RadioItem* artist_list_;
|
||||||
|
RadioItem* tag_list_;
|
||||||
RadioItem* friends_list_;
|
RadioItem* friends_list_;
|
||||||
RadioItem* neighbours_list_;
|
RadioItem* neighbours_list_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "lastfmstationdialog.h"
|
||||||
|
#include "ui_lastfmstationdialog.h"
|
||||||
|
|
||||||
|
LastFMStationDialog::LastFMStationDialog(QWidget* parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
{
|
||||||
|
ui_.setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef LASTFMSTATIONDIALOG_H
|
||||||
|
#define LASTFMSTATIONDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
#include "ui_lastfmstationdialog.h"
|
||||||
|
|
||||||
|
class LastFMStationDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
LastFMStationDialog(QWidget* parent = 0);
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
Artist,
|
||||||
|
Tag,
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetType(Type type);
|
||||||
|
QString content() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::LastFMStationDialog ui_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LASTFMSTATIONDIALOG_H
|
|
@ -0,0 +1,108 @@
|
||||||
|
<?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>120</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Play Artist or Tag</string>
|
||||||
|
</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>
|
||||||
|
</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/>
|
||||||
|
<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>
|
|
@ -42,7 +42,8 @@ SOURCES += main.cpp \
|
||||||
busyindicator.cpp \
|
busyindicator.cpp \
|
||||||
radioplaylistitem.cpp \
|
radioplaylistitem.cpp \
|
||||||
radioloadingindicator.cpp \
|
radioloadingindicator.cpp \
|
||||||
radioview.cpp
|
radioview.cpp \
|
||||||
|
lastfmstationdialog.cpp
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
player.h \
|
player.h \
|
||||||
library.h \
|
library.h \
|
||||||
|
@ -84,12 +85,14 @@ HEADERS += mainwindow.h \
|
||||||
radiomimedata.h \
|
radiomimedata.h \
|
||||||
radioplaylistitem.h \
|
radioplaylistitem.h \
|
||||||
radioloadingindicator.h \
|
radioloadingindicator.h \
|
||||||
radioview.h
|
radioview.h \
|
||||||
|
lastfmstationdialog.h
|
||||||
FORMS += mainwindow.ui \
|
FORMS += mainwindow.ui \
|
||||||
libraryconfig.ui \
|
libraryconfig.ui \
|
||||||
fileview.ui \
|
fileview.ui \
|
||||||
lastfmconfig.ui \
|
lastfmconfig.ui \
|
||||||
radioloadingindicator.ui
|
radioloadingindicator.ui \
|
||||||
|
lastfmstationdialog.ui
|
||||||
RESOURCES += ../data/data.qrc
|
RESOURCES += ../data/data.qrc
|
||||||
OTHER_FILES += ../data/schema.sql \
|
OTHER_FILES += ../data/schema.sql \
|
||||||
../data/mainwindow.css
|
../data/mainwindow.css
|
||||||
|
|
Loading…
Reference in New Issue