Play the next track in a last.fm stream, and handle the end of stream properly

This commit is contained in:
David Sansome 2009-12-26 22:59:11 +00:00
parent 9e285efea7
commit 9206cad0cf
8 changed files with 64 additions and 10 deletions

View File

@ -13,7 +13,8 @@ const char* LastFMService::kSettingsGroup = "Last.fm";
LastFMService::LastFMService(QObject* parent) LastFMService::LastFMService(QObject* parent)
: RadioService("Last.fm", parent), : RadioService("Last.fm", parent),
tuner_(NULL) tuner_(NULL),
initial_tune_(false)
{ {
lastfm::ws::ApiKey = "75d20fb472be99275392aefa2760ea09"; lastfm::ws::ApiKey = "75d20fb472be99275392aefa2760ea09";
lastfm::ws::SharedSecret = "d3072b60ae626be12be69448f5c46e70"; lastfm::ws::SharedSecret = "d3072b60ae626be12be69448f5c46e70";
@ -147,13 +148,35 @@ void LastFMService::StartLoading(const QUrl& url) {
emit LoadingStarted(); emit LoadingStarted();
delete tuner_; delete tuner_;
last_url_ = url; last_url_ = url;
initial_tune_ = true;
tuner_ = new lastfm::RadioTuner(lastfm::RadioStation(url)); tuner_ = new lastfm::RadioTuner(lastfm::RadioStation(url));
connect(tuner_, SIGNAL(trackAvailable()), SLOT(TunerTrackAvailable())); connect(tuner_, SIGNAL(trackAvailable()), SLOT(TunerTrackAvailable()));
connect(tuner_, SIGNAL(error(lastfm::ws::Error)), SLOT(TunerError(lastfm::ws::Error))); connect(tuner_, SIGNAL(error(lastfm::ws::Error)), SLOT(TunerError(lastfm::ws::Error)));
} }
void LastFMService::LoadNext(const QUrl &) {
lastfm::Track track = tuner_->takeNextTrack();
if (track.isNull()) {
emit StreamFinished();
return;
}
emit StreamReady(last_url_, track.url());
Song metadata;
metadata.InitFromLastFM(track);
emit StreamMetadataFound(last_url_, metadata);
}
void LastFMService::TunerError(lastfm::ws::Error error) { void LastFMService::TunerError(lastfm::ws::Error error) {
qDebug() << "Last.fm error" << error;
if (!initial_tune_)
return;
emit LoadingFinished(); emit LoadingFinished();
if (error == lastfm::ws::NotEnoughContent) { if (error == lastfm::ws::NotEnoughContent) {
@ -162,7 +185,6 @@ void LastFMService::TunerError(lastfm::ws::Error error) {
} }
emit StreamError(ErrorString(error)); emit StreamError(ErrorString(error));
qDebug() << "Last.fm error" << error;
} }
QString LastFMService::ErrorString(lastfm::ws::Error error) const { QString LastFMService::ErrorString(lastfm::ws::Error error) const {
@ -195,12 +217,10 @@ QString LastFMService::ErrorString(lastfm::ws::Error error) const {
} }
void LastFMService::TunerTrackAvailable() { void LastFMService::TunerTrackAvailable() {
emit LoadingFinished(); if (initial_tune_) {
emit LoadingFinished();
lastfm::Track track = tuner_->takeNextTrack(); LoadNext(last_url_);
emit StreamReady(last_url_, track.url()); initial_tune_ = false;
}
Song metadata;
metadata.InitFromLastFM(track);
emit StreamMetadataFound(last_url_, metadata);
} }

View File

@ -27,7 +27,9 @@ class LastFMService : public RadioService {
RadioItem* CreateRootItem(RadioItem* parent); RadioItem* CreateRootItem(RadioItem* parent);
void LazyPopulate(RadioItem *item); void LazyPopulate(RadioItem *item);
QList<RadioItem::PlaylistData> DataForItem(RadioItem* item); QList<RadioItem::PlaylistData> DataForItem(RadioItem* item);
void StartLoading(const QUrl& url); void StartLoading(const QUrl& url);
void LoadNext(const QUrl& url);
void Authenticate(const QString& username, const QString& password); void Authenticate(const QString& username, const QString& password);
@ -49,6 +51,7 @@ class LastFMService : public RadioService {
LastFMConfig* config_; LastFMConfig* config_;
lastfm::RadioTuner* tuner_; lastfm::RadioTuner* tuner_;
QUrl last_url_; QUrl last_url_;
bool initial_tune_;
}; };
#endif // LASTFMSERVICE_H #endif // LASTFMSERVICE_H

View File

@ -17,7 +17,7 @@ Player::Player(Playlist* playlist, QObject* parent)
SetVolume(settings_.value("volume", 50).toInt()); SetVolume(settings_.value("volume", 50).toInt());
connect(engine_, SIGNAL(stateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State))); connect(engine_, SIGNAL(stateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State)));
connect(engine_, SIGNAL(trackEnded()), SLOT(Next())); connect(engine_, SIGNAL(trackEnded()), SLOT(TrackEnded()));
} }
void Player::Next() { void Player::Next() {
@ -32,6 +32,20 @@ void Player::Next() {
PlayAt(i); PlayAt(i);
} }
void Player::TrackEnded() {
int i = playlist_->current_item();
if (i == -1) {
Stop();
return;
}
// Is this track a radio station (like Last.fm) that can have another track?
if (playlist_->item_at(i)->LoadNext())
return;
Next();
}
void Player::PlayPause() { void Player::PlayPause() {
switch (engine_->state()) { switch (engine_->state()) {
case Engine::Paused: case Engine::Paused:

View File

@ -27,6 +27,7 @@ class Player : public QObject {
void Stop(); void Stop();
void SetVolume(int value); void SetVolume(int value);
void TrackEnded();
void StreamReady(const QUrl& original_url, const QUrl& media_url); void StreamReady(const QUrl& original_url, const QUrl& media_url);
signals: signals:

View File

@ -39,6 +39,10 @@ class PlaylistItem {
virtual bool StartLoading() { return false; } virtual bool StartLoading() { return false; }
virtual QUrl Url() = 0; virtual QUrl Url() = 0;
// If the item is a radio station that can play another song after one has
// finished then it should do so and return true
virtual bool LoadNext() { return false; }
virtual void SetTemporaryMetadata(const Song& metadata) {Q_UNUSED(metadata)} virtual void SetTemporaryMetadata(const Song& metadata) {Q_UNUSED(metadata)}
virtual void ClearTemporaryMetadata() {} virtual void ClearTemporaryMetadata() {}
}; };

View File

@ -65,6 +65,14 @@ bool RadioPlaylistItem::StartLoading() {
return true; return true;
} }
bool RadioPlaylistItem::LoadNext() {
if (service_) {
service_->LoadNext(url_);
return true;
}
return false;
}
QUrl RadioPlaylistItem::Url() { QUrl RadioPlaylistItem::Url() {
return url_; return url_;
} }

View File

@ -27,6 +27,8 @@ class RadioPlaylistItem : public PlaylistItem {
bool StartLoading(); bool StartLoading();
QUrl Url(); QUrl Url();
bool LoadNext();
void SetTemporaryMetadata(const Song& metadata); void SetTemporaryMetadata(const Song& metadata);
void ClearTemporaryMetadata(); void ClearTemporaryMetadata();

View File

@ -22,7 +22,9 @@ class RadioService : public QObject {
virtual void LazyPopulate(RadioItem* item) = 0; virtual void LazyPopulate(RadioItem* item) = 0;
virtual QList<RadioItem::PlaylistData> DataForItem(RadioItem* item) = 0; virtual QList<RadioItem::PlaylistData> DataForItem(RadioItem* item) = 0;
virtual void StartLoading(const QUrl& url) = 0; virtual void StartLoading(const QUrl& url) = 0;
virtual void LoadNext(const QUrl& url) = 0;
signals: signals:
void LoadingStarted(); void LoadingStarted();