Scrobble tracks

This commit is contained in:
David Sansome 2009-12-29 19:57:33 +00:00
parent 38feb17697
commit 72f793a002
7 changed files with 99 additions and 43 deletions

View File

@ -243,20 +243,13 @@ bool LastFMService::InitScrobbler() {
if (!IsAuthenticated())
return false;
if (!scrobbler_) {
if (!scrobbler_)
scrobbler_ = new lastfm::Audioscrobbler(kAudioscrobblerClientId);
connect(scrobbler_, SIGNAL(status(int)), SLOT(ScrobblerStatus(int)));
}
return true;
}
lastfm::Track LastFMService::TrackFromSong(const Song &song) const {
qDebug() << song.title() << last_track_.title();
qDebug() << song.artist() << last_track_.artist();
qDebug() << song.album() << last_track_.album();
qDebug() << last_track_.fingerprintId() << last_track_.mbid();
if (song.title() == last_track_.title() &&
song.artist() == last_track_.artist() &&
song.album() == last_track_.album())
@ -291,7 +284,3 @@ void LastFMService::Ban(const Song& song) {
lastfm::MutableTrack mtrack(TrackFromSong(song));
mtrack.ban();
}
void LastFMService::ScrobblerStatus(int status) {
qDebug() << static_cast<lastfm::Audioscrobbler::Status>(status);
}

View File

@ -54,8 +54,6 @@ class LastFMService : public RadioService {
void TunerTrackAvailable();
void TunerError(lastfm::ws::Error error);
void ScrobblerStatus(int status);
private:
RadioItem* CreateStationItem(ItemType type, const QString& name,
const QString& icon, RadioItem* parent);

View File

@ -6,6 +6,8 @@
#include "songplaylistitem.h"
#include "systemtrayicon.h"
#include "radiomodel.h"
#include "enginebase.h"
#include "lastfmservice.h"
#include <QFileSystemModel>
#include <QSortFilterProxyModel>
@ -18,17 +20,20 @@
#include <QCloseEvent>
#include <QSignalMapper>
#include <cmath>
const int MainWindow::kStateVersion = 1;
const char* MainWindow::kSettingsGroup = "MainWindow";
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
tray_icon_(new SystemTrayIcon(this)),
radio_model_(new RadioModel(this)),
playlist_(new Playlist(this)),
player_(new Player(playlist_, radio_model_->GetLastFMService(), this)),
library_(new Library(player_->GetEngine(), this)),
library_sort_model_(new QSortFilterProxyModel(this)),
tray_icon_(new SystemTrayIcon(this))
track_position_timer_(new QTimer(this))
{
ui_.setupUi(this);
tray_icon_->setIcon(windowIcon());
@ -38,6 +43,9 @@ MainWindow::MainWindow(QWidget *parent)
ui_.volume->setValue(player_->GetVolume());
ui_.last_fm_controls->hide();
track_position_timer_->setInterval(1000);
connect(track_position_timer_, SIGNAL(timeout()), SLOT(UpdateTrackPosition()));
// Models
library_sort_model_->setSourceModel(library_);
library_sort_model_->setSortRole(Library::Role_SortText);
@ -218,6 +226,8 @@ void MainWindow::MediaStopped() {
ui_.action_ban->setVisible(false);
ui_.action_love->setVisible(false);
ui_.last_fm_controls->hide();
track_position_timer_->stop();
}
void MainWindow::MediaPaused() {
@ -227,6 +237,8 @@ void MainWindow::MediaPaused() {
ui_.action_play_pause->setText("Play");
ui_.action_play_pause->setEnabled(true);
track_position_timer_->stop();
}
void MainWindow::MediaPlaying() {
@ -242,6 +254,9 @@ void MainWindow::MediaPlaying() {
ui_.action_ban->setVisible(lastfm);
ui_.action_love->setVisible(lastfm);
ui_.last_fm_controls->setVisible(lastfm);
track_position_timer_->start();
UpdateTrackPosition();
}
void MainWindow::resizeEvent(QResizeEvent*) {
@ -292,7 +307,7 @@ void MainWindow::TrayClicked(QSystemTrayIcon::ActivationReason reason) {
}
void MainWindow::StopAfterCurrent() {
playlist_->StopAfter(playlist_->current_item());
playlist_->StopAfter(playlist_->current_index());
}
void MainWindow::closeEvent(QCloseEvent* event) {
@ -321,3 +336,13 @@ void MainWindow::FilePathChanged(const QString& path) {
settings.beginGroup(kSettingsGroup);
settings.setValue("file_path", path);
}
void MainWindow::UpdateTrackPosition() {
int position = std::floor(float(player_->GetEngine()->position()) / 1000.0 + 0.5);
if (!playlist_->has_scrobbled() &&
position >= playlist_->scrobble_point()) {
radio_model_->GetLastFMService()->Scrobble(playlist_->current_item_metadata());
playlist_->set_scrobbled(true);
}
}

View File

@ -46,6 +46,8 @@ class MainWindow : public QMainWindow {
void VolumeWheelEvent(int delta);
void TrayClicked(QSystemTrayIcon::ActivationReason reason);
void UpdateTrackPosition();
private:
void SaveGeometry();
@ -54,6 +56,7 @@ class MainWindow : public QMainWindow {
static const char* kSettingsGroup;
Ui::MainWindow ui_;
SystemTrayIcon* tray_icon_;
RadioModel* radio_model_;
Playlist* playlist_;
@ -62,7 +65,7 @@ class MainWindow : public QMainWindow {
QSortFilterProxyModel* library_sort_model_;
SystemTrayIcon* tray_icon_;
QTimer* track_position_timer_;
};
#endif // MAINWINDOW_H

View File

@ -23,8 +23,8 @@ Player::Player(Playlist* playlist, LastFMService* lastfm, QObject* parent)
}
void Player::Next() {
int i = playlist_->next_item();
playlist_->set_current_item(i);
int i = playlist_->next_index();
playlist_->set_current_index(i);
if (i == -1) {
Stop();
return;
@ -35,7 +35,7 @@ void Player::Next() {
}
void Player::TrackEnded() {
int i = playlist_->current_item();
int i = playlist_->current_index();
if (i == -1 || playlist_->stop_after_current()) {
Stop();
return;
@ -63,7 +63,7 @@ void Player::PlayPause() {
case Engine::Empty:
case Engine::Idle: {
int i = playlist_->current_item();
int i = playlist_->current_index();
if (i == -1) {
if (playlist_->rowCount() == 0)
break;
@ -78,12 +78,12 @@ void Player::PlayPause() {
void Player::Stop() {
qDebug() << "Stopping";
engine_->stop();
playlist_->set_current_item(-1);
playlist_->set_current_index(-1);
}
void Player::Previous() {
int i = playlist_->previous_item();
playlist_->set_current_item(i);
int i = playlist_->previous_index();
playlist_->set_current_index(i);
if (i == -1) {
Stop();
return;
@ -115,7 +115,7 @@ Engine::State Player::GetState() const {
}
void Player::PlayAt(int index) {
playlist_->set_current_item(index);
playlist_->set_current_index(index);
PlaylistItem* item = playlist_->item_at(index);
@ -128,7 +128,7 @@ void Player::PlayAt(int index) {
}
void Player::StreamReady(const QUrl& original_url, const QUrl& media_url) {
int current_index = playlist_->current_item();
int current_index = playlist_->current_index();
if (current_index == -1)
return;

View File

@ -13,13 +13,17 @@
#include <boost/bind.hpp>
#include <lastfm/ScrobblePoint>
const char* Playlist::kRowsMimetype = "application/x-tangerine-playlist-rows";
const char* Playlist::kSettingsGroup = "Playlist";
Playlist::Playlist(QObject *parent) :
QAbstractListModel(parent),
current_is_paused_(false),
ignore_sorting_(false)
ignore_sorting_(false),
scrobble_point_(-1),
has_scrobbled_(false)
{
}
@ -71,28 +75,28 @@ QVariant Playlist::data(const QModelIndex& index, int role) const {
}
}
int Playlist::current_item() const {
int Playlist::current_index() const {
return current_item_.isValid() ? current_item_.row() : -1;
}
int Playlist::next_item() const {
int i = current_item() + 1;
int Playlist::next_index() const {
int i = current_index() + 1;
if (i >= items_.count())
return -1;
if (stop_after_.isValid() && current_item() == stop_after_.row())
if (stop_after_.isValid() && current_index() == stop_after_.row())
return -1;
return i;
}
int Playlist::previous_item() const {
int i = current_item() - 1;
int Playlist::previous_index() const {
int i = current_index() - 1;
if (i < 0)
return -1;
return i;
}
void Playlist::set_current_item(int i) {
void Playlist::set_current_index(int i) {
QModelIndex old_current = current_item_;
ClearStreamMetadata();
@ -102,6 +106,8 @@ void Playlist::set_current_item(int i) {
emit dataChanged(old_current, old_current.sibling(old_current.row(), ColumnCount));
if (current_item_.isValid())
emit dataChanged(current_item_, current_item_.sibling(current_item_.row(), ColumnCount));
UpdateScrobblePoint();
}
Qt::ItemFlags Playlist::flags(const QModelIndex &index) const {
@ -387,7 +393,7 @@ bool Playlist::removeRows(int row, int count, const QModelIndex& parent) {
// Remove items
for (int i=0 ; i<count ; ++i)
items_.removeAt(row);
delete items_.takeAt(row);
endRemoveRows();
@ -418,6 +424,7 @@ void Playlist::SetStreamMetadata(const QUrl& url, const Song& song) {
return;
item->SetTemporaryMetadata(song);
UpdateScrobblePoint();
emit dataChanged(index(current_item_.row(), 0), index(current_item_.row(), ColumnCount));
}
@ -428,6 +435,7 @@ void Playlist::ClearStreamMetadata() {
PlaylistItem* item = items_[current_item_.row()];
item->ClearTemporaryMetadata();
UpdateScrobblePoint();
emit dataChanged(index(current_item_.row(), 0), index(current_item_.row(), ColumnCount));
}
@ -437,14 +445,34 @@ bool Playlist::stop_after_current() const {
stop_after_.row() == current_item_.row();
}
PlaylistItem::Options Playlist::current_item_options() const {
int i = current_item();
PlaylistItem* Playlist::current_item() const {
int i = current_index();
if (i == -1)
return PlaylistItem::Default;
return NULL;
PlaylistItem* item = item_at(i);
return item_at(i);
}
PlaylistItem::Options Playlist::current_item_options() const {
PlaylistItem* item = current_item();
if (!item)
return PlaylistItem::Default;
return item->options();
}
Song Playlist::current_item_metadata() const {
PlaylistItem* item = current_item();
if (!item)
return Song();
return item->Metadata();
}
void Playlist::UpdateScrobblePoint() {
int length = current_item_metadata().length();
ScrobblePoint point(length / 2);
scrobble_point_ = point;
has_scrobbled_ = false;
}

View File

@ -43,12 +43,21 @@ class Playlist : public QAbstractListModel {
void Restore();
// Accessors
int current_item() const;
int next_item() const;
int previous_item() const;
int current_index() const;
int next_index() const;
int previous_index() const;
bool stop_after_current() const;
PlaylistItem* item_at(int index) const { return items_[index]; }
PlaylistItem* current_item() const;
PlaylistItem::Options current_item_options() const;
Song current_item_metadata() const;
// Scrobbling
int scrobble_point() const { return scrobble_point_; }
bool has_scrobbled() const { return has_scrobbled_; }
void set_scrobbled(bool v) { has_scrobbled_ = v; }
// Changing the playlist
QModelIndex InsertItems(const QList<PlaylistItem*>& items, int after = -1);
@ -73,7 +82,7 @@ class Playlist : public QAbstractListModel {
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex());
public slots:
void set_current_item(int index);
void set_current_index(int index);
void Paused();
void Playing();
void Stopped();
@ -84,6 +93,7 @@ class Playlist : public QAbstractListModel {
private:
void SetCurrentIsPaused(bool paused);
void UpdateScrobblePoint();
private:
QList<PlaylistItem*> items_;
@ -92,6 +102,9 @@ class Playlist : public QAbstractListModel {
QPersistentModelIndex stop_after_;
bool current_is_paused_;
int scrobble_point_;
bool has_scrobbled_;
// Hack to stop QTreeView::setModel sorting the playlist
bool ignore_sorting_;
};