Scrobble tracks
This commit is contained in:
parent
38feb17697
commit
72f793a002
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue