Tag and artist radio

This commit is contained in:
David Sansome 2009-12-30 02:15:38 +00:00
parent bfc81e4d5c
commit efefc35d6e
7 changed files with 265 additions and 18 deletions

4
TODO
View File

@ -8,10 +8,6 @@
- Make QSortFilterProxyModel on the library obey hasChildren()
- More columns in playlist
Last.fm:
- Artist/tag/etc. radio
- More types of radio
Long-term:
- iPod

View File

@ -2,6 +2,7 @@
#include "lastfmconfig.h"
#include "radioitem.h"
#include "song.h"
#include "lastfmstationdialog.h"
#include <lastfm/ws.h>
#include <lastfm/misc.h>
@ -21,9 +22,12 @@ LastFMService::LastFMService(QObject* parent)
: RadioService(kServiceName, parent),
tuner_(NULL),
scrobbler_(NULL),
station_dialog_(new LastFMStationDialog),
context_menu_(new QMenu),
initial_tune_(false),
scrobbling_enabled_(false),
artist_list_(NULL),
tag_list_(NULL),
friends_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()));
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...",
config_, SLOT(show()));
add_artist_action_->setEnabled(false);
add_tag_action_->setEnabled(false);
}
LastFMService::~LastFMService() {
delete config_;
delete station_dialog_;
delete context_menu_;
}
@ -75,8 +84,6 @@ RadioItem* LastFMService::CreateRootItem(RadioItem* parent) {
}
void LastFMService::LazyPopulate(RadioItem *item) {
RadioItem* c = NULL;
switch (item->type) {
case RadioItem::Type_Service:
// 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_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
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_->icon = QIcon(":last.fm/my_friends.png");
@ -103,6 +112,9 @@ void LastFMService::LazyPopulate(RadioItem *item) {
if (!IsAuthenticated())
config_->show();
add_artist_action_->setEnabled(true);
add_tag_action_->setEnabled(true);
break;
case Type_MyFriends:
@ -204,6 +216,12 @@ QUrl LastFMService::UrlForItem(const RadioItem* item) const {
case Type_OtherUserNeighbourhood:
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();
}
@ -220,6 +238,8 @@ QString LastFMService::TitleForItem(const RadioItem* item) const {
case Type_OtherUserRadio: return item->key + "'s Library";
case Type_OtherUserLoved: return item->key + "'s Loved Tracks";
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();
}
@ -444,3 +464,62 @@ void LastFMService::RefreshNeighboursFinished() {
void LastFMService::AddToPlaylist() {
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();
}

View File

@ -3,6 +3,7 @@
#include "radioservice.h"
#include "song.h"
#include "lastfmstationdialog.h"
#include <lastfm/RadioTuner>
@ -37,6 +38,8 @@ class LastFMService : public RadioService {
Type_OtherUserRadio,
Type_OtherUserLoved,
Type_OtherUserNeighbourhood,
Type_Artist,
Type_Tag,
};
// RadioService
@ -80,6 +83,8 @@ class LastFMService : public RadioService {
void TunerError(lastfm::ws::Error error);
void AddToPlaylist();
void AddArtistRadio();
void AddTagRadio();
private:
RadioItem* CreateStationItem(ItemType type, const QString& name,
@ -89,6 +94,12 @@ class LastFMService : public RadioService {
lastfm::Track TrackFromSong(const Song& song) const;
void RefreshFriends();
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:
lastfm::RadioTuner* tuner_;
@ -96,9 +107,13 @@ class LastFMService : public RadioService {
lastfm::Track last_track_;
LastFMConfig* config_;
LastFMStationDialog* station_dialog_;
QMenu* context_menu_;
QAction* play_action_;
QAction* remove_action_;
QAction* add_artist_action_;
QAction* add_tag_action_;
RadioItem* context_item_;
QUrl last_url_;
@ -106,6 +121,8 @@ class LastFMService : public RadioService {
bool scrobbling_enabled_;
RadioItem* artist_list_;
RadioItem* tag_list_;
RadioItem* friends_list_;
RadioItem* neighbours_list_;
};

View File

@ -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();
}

26
src/lastfmstationdialog.h Normal file
View File

@ -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

108
src/lastfmstationdialog.ui Normal file
View File

@ -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 &lt;b&gt;artist&lt;/b&gt; or &lt;b&gt;tag&lt;/b&gt; 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>

View File

@ -42,7 +42,8 @@ SOURCES += main.cpp \
busyindicator.cpp \
radioplaylistitem.cpp \
radioloadingindicator.cpp \
radioview.cpp
radioview.cpp \
lastfmstationdialog.cpp
HEADERS += mainwindow.h \
player.h \
library.h \
@ -84,12 +85,14 @@ HEADERS += mainwindow.h \
radiomimedata.h \
radioplaylistitem.h \
radioloadingindicator.h \
radioview.h
radioview.h \
lastfmstationdialog.h
FORMS += mainwindow.ui \
libraryconfig.ui \
fileview.ui \
lastfmconfig.ui \
radioloadingindicator.ui
radioloadingindicator.ui \
lastfmstationdialog.ui
RESOURCES += ../data/data.qrc
OTHER_FILES += ../data/schema.sql \
../data/mainwindow.css