Love, ban, skip last.fm tracks
This commit is contained in:
parent
5e514c42b6
commit
b5be7d6cb9
2
TODO
2
TODO
@ -10,8 +10,6 @@
|
||||
|
||||
Last.fm:
|
||||
- Artist/tag/etc. radio
|
||||
- Skip, love
|
||||
- Disable the pause button
|
||||
- Double click from radio list
|
||||
- Right click on radio list to configure Last.fm
|
||||
- More types of radio
|
||||
|
@ -10,8 +10,6 @@ LastFMConfig::LastFMConfig(LastFMService* service, QWidget *parent)
|
||||
service_(service)
|
||||
{
|
||||
ui_.setupUi(this);
|
||||
|
||||
ui_.username->setText(lastfm::ws::Username);
|
||||
ui_.busy->hide();
|
||||
|
||||
connect(service_, SIGNAL(AuthenticationComplete(bool)), SLOT(AuthenticationComplete(bool)));
|
||||
@ -27,6 +25,8 @@ void LastFMConfig::accept() {
|
||||
ui_.button_box->setEnabled(false);
|
||||
|
||||
service_->Authenticate(ui_.username->text(), ui_.password->text());
|
||||
|
||||
emit ScrobblingEnabledChanged(ui_.scrobble->isChecked());
|
||||
}
|
||||
|
||||
void LastFMConfig::AuthenticationComplete(bool success) {
|
||||
|
@ -15,11 +15,15 @@ class LastFMConfig : public QDialog {
|
||||
|
||||
void accept();
|
||||
|
||||
Ui::LastFMConfig ui_;
|
||||
|
||||
signals:
|
||||
void ScrobblingEnabledChanged(bool value);
|
||||
|
||||
private slots:
|
||||
void AuthenticationComplete(bool success);
|
||||
|
||||
private:
|
||||
Ui::LastFMConfig ui_;
|
||||
LastFMService* service_;
|
||||
};
|
||||
|
||||
|
@ -52,6 +52,9 @@
|
||||
<property name="text">
|
||||
<string>Scrobble tracks that I listen to</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -20,7 +20,8 @@ LastFMService::LastFMService(QObject* parent)
|
||||
: RadioService(kServiceName, parent),
|
||||
tuner_(NULL),
|
||||
scrobbler_(NULL),
|
||||
initial_tune_(false)
|
||||
initial_tune_(false),
|
||||
scrobbling_enabled_(false)
|
||||
{
|
||||
lastfm::ws::ApiKey = kApiKey;
|
||||
lastfm::ws::SharedSecret = kSecret;
|
||||
@ -29,8 +30,13 @@ LastFMService::LastFMService(QObject* parent)
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
lastfm::ws::Username = settings.value("username").toString();
|
||||
lastfm::ws::SessionKey = settings.value("session").toString();
|
||||
scrobbling_enabled_ = settings.value("scrobbling_enabled", true).toBool();
|
||||
|
||||
config_ = new LastFMConfig(this);
|
||||
connect(config_, SIGNAL(ScrobblingEnabledChanged(bool)), SLOT(ScrobblingEnabledChangedSlot(bool)));
|
||||
|
||||
config_->ui_.username->setText(lastfm::ws::Username);
|
||||
config_->ui_.scrobble->setEnabled(scrobbling_enabled_);
|
||||
}
|
||||
|
||||
LastFMService::~LastFMService() {
|
||||
@ -41,6 +47,16 @@ bool LastFMService::IsAuthenticated() const {
|
||||
return !lastfm::ws::SessionKey.isEmpty();
|
||||
}
|
||||
|
||||
void LastFMService::ScrobblingEnabledChangedSlot(bool value) {
|
||||
scrobbling_enabled_ = value;
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
settings.setValue("scrobbling_enabled", scrobbling_enabled_);
|
||||
|
||||
emit ScrobblingEnabledChanged(value);
|
||||
}
|
||||
|
||||
RadioItem* LastFMService::CreateRootItem(RadioItem* parent) {
|
||||
RadioItem* item = new RadioItem(this, RadioItem::Type_Service, "Last.fm", parent);
|
||||
item->icon = QIcon(":last.fm/as.png");
|
||||
@ -240,7 +256,7 @@ void LastFMService::TunerTrackAvailable() {
|
||||
}
|
||||
|
||||
bool LastFMService::InitScrobbler() {
|
||||
if (!IsAuthenticated())
|
||||
if (!IsAuthenticated() || !IsScrobblingEnabled())
|
||||
return false;
|
||||
|
||||
if (!scrobbler_)
|
||||
@ -282,6 +298,9 @@ void LastFMService::Scrobble() {
|
||||
}
|
||||
|
||||
void LastFMService::Love() {
|
||||
if (!IsAuthenticated())
|
||||
config_->show();
|
||||
|
||||
lastfm::MutableTrack mtrack(last_track_);
|
||||
mtrack.love();
|
||||
}
|
||||
@ -289,4 +308,7 @@ void LastFMService::Love() {
|
||||
void LastFMService::Ban() {
|
||||
lastfm::MutableTrack mtrack(last_track_);
|
||||
mtrack.ban();
|
||||
|
||||
Scrobble();
|
||||
LoadNext(last_url_);
|
||||
}
|
||||
|
@ -38,18 +38,23 @@ class LastFMService : public RadioService {
|
||||
bool ShowLastFmControls() const { return true; }
|
||||
|
||||
bool IsAuthenticated() const;
|
||||
bool IsScrobblingEnabled() const { return scrobbling_enabled_; }
|
||||
void Authenticate(const QString& username, const QString& password);
|
||||
|
||||
void NowPlaying(const Song& song);
|
||||
|
||||
public slots:
|
||||
void Scrobble();
|
||||
void Love();
|
||||
void Ban();
|
||||
|
||||
signals:
|
||||
void AuthenticationComplete(bool success);
|
||||
void ScrobblingEnabledChanged(bool value);
|
||||
|
||||
private slots:
|
||||
void AuthenticateReplyFinished();
|
||||
void ScrobblingEnabledChangedSlot(bool value);
|
||||
|
||||
void TunerTrackAvailable();
|
||||
void TunerError(lastfm::ws::Error error);
|
||||
@ -69,6 +74,8 @@ class LastFMService : public RadioService {
|
||||
LastFMConfig* config_;
|
||||
QUrl last_url_;
|
||||
bool initial_tune_;
|
||||
|
||||
bool scrobbling_enabled_;
|
||||
};
|
||||
|
||||
#endif // LASTFMSERVICE_H
|
||||
|
@ -41,7 +41,6 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
tray_icon_->show();
|
||||
|
||||
ui_.volume->setValue(player_->GetVolume());
|
||||
ui_.last_fm_controls->hide();
|
||||
|
||||
track_position_timer_->setInterval(1000);
|
||||
connect(track_position_timer_, SIGNAL(timeout()), SLOT(UpdateTrackPosition()));
|
||||
@ -75,6 +74,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(ui_.action_quit, SIGNAL(triggered()), qApp, SLOT(quit()));
|
||||
connect(ui_.action_stop_after_this_track, SIGNAL(triggered()), SLOT(StopAfterCurrent()));
|
||||
connect(ui_.library_filter, SIGNAL(textChanged(QString)), library_, SLOT(SetFilterText(QString)));
|
||||
connect(ui_.action_ban, SIGNAL(triggered()), radio_model_->GetLastFMService(), SLOT(Ban()));
|
||||
connect(ui_.action_love, SIGNAL(triggered()), SLOT(Love()));
|
||||
|
||||
// Give actions to buttons
|
||||
ui_.forward_button->setDefaultAction(ui_.action_next_track);
|
||||
@ -155,6 +156,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(radio_model_, SIGNAL(StreamFinished()), player_, SLOT(Next()));
|
||||
connect(radio_model_, SIGNAL(StreamReady(QUrl,QUrl)), player_, SLOT(StreamReady(QUrl,QUrl)));
|
||||
connect(radio_model_, SIGNAL(StreamMetadataFound(QUrl,Song)), playlist_, SLOT(SetStreamMetadata(QUrl,Song)));
|
||||
connect(radio_model_->GetLastFMService(), SIGNAL(ScrobblingEnabledChanged(bool)), SLOT(ScrobblingEnabledChanged(bool)));
|
||||
|
||||
// Tray icon
|
||||
QMenu* tray_menu = new QMenu(this);
|
||||
@ -223,9 +225,8 @@ void MainWindow::MediaStopped() {
|
||||
|
||||
ui_.action_play_pause->setEnabled(true);
|
||||
|
||||
ui_.action_ban->setVisible(false);
|
||||
ui_.action_love->setVisible(false);
|
||||
ui_.last_fm_controls->hide();
|
||||
ui_.action_ban->setEnabled(false);
|
||||
ui_.action_love->setEnabled(false);
|
||||
|
||||
track_position_timer_->stop();
|
||||
}
|
||||
@ -250,15 +251,21 @@ void MainWindow::MediaPlaying() {
|
||||
ui_.action_play_pause->setEnabled(
|
||||
! playlist_->current_item_options() & PlaylistItem::PauseDisabled);
|
||||
|
||||
bool lastfm = playlist_->current_item_options() & PlaylistItem::LastFMControls;
|
||||
ui_.action_ban->setVisible(lastfm);
|
||||
ui_.action_love->setVisible(lastfm);
|
||||
ui_.last_fm_controls->setVisible(lastfm);
|
||||
bool is_lastfm = playlist_->current_item_options() & PlaylistItem::LastFMControls;
|
||||
LastFMService* lastfm = radio_model_->GetLastFMService();
|
||||
|
||||
ui_.action_ban->setEnabled(lastfm->IsScrobblingEnabled() && is_lastfm);
|
||||
ui_.action_love->setEnabled(lastfm->IsScrobblingEnabled());
|
||||
|
||||
track_position_timer_->start();
|
||||
UpdateTrackPosition();
|
||||
}
|
||||
|
||||
void MainWindow::ScrobblingEnabledChanged(bool value) {
|
||||
ui_.action_ban->setEnabled(value);
|
||||
ui_.action_love->setEnabled(value);
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent*) {
|
||||
SaveGeometry();
|
||||
}
|
||||
@ -340,9 +347,16 @@ void MainWindow::FilePathChanged(const QString& path) {
|
||||
void MainWindow::UpdateTrackPosition() {
|
||||
int position = std::floor(float(player_->GetEngine()->position()) / 1000.0 + 0.5);
|
||||
|
||||
LastFMService* lastfm = radio_model_->GetLastFMService();
|
||||
|
||||
if (!playlist_->has_scrobbled() &&
|
||||
position >= playlist_->scrobble_point()) {
|
||||
radio_model_->GetLastFMService()->Scrobble();
|
||||
lastfm->Scrobble();
|
||||
playlist_->set_scrobbled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::Love() {
|
||||
radio_model_->GetLastFMService()->Love();
|
||||
ui_.action_love->setEnabled(false);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ class Player;
|
||||
class Library;
|
||||
class LibraryConfig;
|
||||
class RadioModel;
|
||||
class Song;
|
||||
|
||||
class QSortFilterProxyModel;
|
||||
class SystemTrayIcon;
|
||||
@ -48,6 +49,9 @@ class MainWindow : public QMainWindow {
|
||||
|
||||
void UpdateTrackPosition();
|
||||
|
||||
void ScrobblingEnabledChanged(bool value);
|
||||
void Love();
|
||||
|
||||
private:
|
||||
void SaveGeometry();
|
||||
|
||||
|
@ -535,6 +535,9 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_love">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../data/data.qrc">
|
||||
<normaloff>:/last.fm/love.png</normaloff>:/last.fm/love.png</iconset>
|
||||
@ -542,11 +545,11 @@
|
||||
<property name="text">
|
||||
<string>Love</string>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</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>
|
||||
@ -554,9 +557,6 @@
|
||||
<property name="text">
|
||||
<string>Ban</string>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
|
@ -23,6 +23,11 @@ Player::Player(Playlist* playlist, LastFMService* lastfm, QObject* parent)
|
||||
}
|
||||
|
||||
void Player::Next() {
|
||||
if (playlist_->current_item_options() & PlaylistItem::ContainsMultipleTracks) {
|
||||
playlist_->current_item()->LoadNext();
|
||||
return;
|
||||
}
|
||||
|
||||
int i = playlist_->next_index();
|
||||
playlist_->set_current_index(i);
|
||||
if (i == -1) {
|
||||
@ -30,7 +35,6 @@ void Player::Next() {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Playing item" << i;
|
||||
PlayAt(i);
|
||||
}
|
||||
|
||||
@ -41,12 +45,7 @@ void Player::TrackEnded() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Is this track a radio station (like Last.fm) that can have another track?
|
||||
PlaylistItem* item = playlist_->item_at(i);
|
||||
if (item->options() & PlaylistItem::ContainsMultipleTracks)
|
||||
item->LoadNext();
|
||||
else
|
||||
Next();
|
||||
Next();
|
||||
}
|
||||
|
||||
void Player::PlayPause() {
|
||||
@ -123,7 +122,9 @@ void Player::PlayAt(int index) {
|
||||
item->StartLoading();
|
||||
else {
|
||||
engine_->play(item->Url());
|
||||
lastfm_->NowPlaying(item->Metadata());
|
||||
|
||||
if (lastfm_->IsScrobblingEnabled())
|
||||
lastfm_->NowPlaying(item->Metadata());
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,5 +138,6 @@ void Player::StreamReady(const QUrl& original_url, const QUrl& media_url) {
|
||||
return;
|
||||
|
||||
engine_->play(media_url);
|
||||
|
||||
lastfm_->NowPlaying(item->Metadata());
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ PlaylistHeader::PlaylistHeader(Qt::Orientation orientation, QWidget* parent)
|
||||
show_action->setMenu(show_menu_);
|
||||
|
||||
connect(show_mapper_, SIGNAL(mapped(int)), SLOT(ToggleVisible(int)));
|
||||
connect(this, SIGNAL(sectionMoved(int,int,int)), SLOT(SectionMoved()));
|
||||
}
|
||||
|
||||
void PlaylistHeader::contextMenuEvent(QContextMenuEvent* e) {
|
||||
@ -60,38 +59,3 @@ void PlaylistHeader::HideCurrent() {
|
||||
void PlaylistHeader::ToggleVisible(int section) {
|
||||
setSectionHidden(section, !isSectionHidden(section));
|
||||
}
|
||||
|
||||
void PlaylistHeader::resizeEvent(QResizeEvent *event) {
|
||||
if (!event->oldSize().isValid())
|
||||
return;
|
||||
|
||||
const float scale = float(event->size().width()) / event->oldSize().width();
|
||||
|
||||
for (int i=0 ; i<count() ; ++i) {
|
||||
resizeSection(i, sectionSize(i) * scale);
|
||||
}
|
||||
}
|
||||
|
||||
void PlaylistHeader::SectionMoved() {
|
||||
for (int i=0 ; i<count() ; ++i) {
|
||||
setResizeMode(i, Interactive);
|
||||
if (sectionSize(i) < 20)
|
||||
resizeSection(i, 50);
|
||||
}
|
||||
|
||||
setResizeMode(logicalIndex(LastVisualIndex()), Stretch);
|
||||
}
|
||||
|
||||
int PlaylistHeader::LastVisualIndex() const {
|
||||
int ret = -1;
|
||||
for (int i=0 ; i<count() ; ++i) {
|
||||
if (isSectionHidden(i))
|
||||
continue;
|
||||
|
||||
ret = qMax(visualIndex(i), ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,17 +14,13 @@ class PlaylistHeader : public QHeaderView {
|
||||
|
||||
// QWidget
|
||||
void contextMenuEvent(QContextMenuEvent* e);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private slots:
|
||||
void HideCurrent();
|
||||
void ToggleVisible(int section);
|
||||
|
||||
void SectionMoved();
|
||||
|
||||
private:
|
||||
void AddColumnAction(int index);
|
||||
int LastVisualIndex() const;
|
||||
|
||||
private:
|
||||
int menu_section_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user