1
0
mirror of https://github.com/clementine-player/Clementine synced 2024-12-16 11:19:18 +01:00

Refactor and fix most of the MPRIS code. Fixes issue #374

This commit is contained in:
David Sansome 2010-12-04 22:27:58 +00:00
parent 0186c87bae
commit 987dd8c57a
10 changed files with 654 additions and 498 deletions

View File

@ -550,24 +550,24 @@ if(NOT APPLE AND NOT WIN32)
# MPRIS DBUS interfaces
qt4_add_dbus_adaptor(SOURCES
dbus/org.freedesktop.MediaPlayer.player.xml
core/mpris.h MPRIS core/mpris_player MprisPlayer)
core/mpris.h mpris::Mpris1Player core/mpris_player MprisPlayer)
qt4_add_dbus_adaptor(SOURCES
dbus/org.freedesktop.MediaPlayer.root.xml
core/mpris.h MPRIS core/mpris_root MprisRoot)
core/mpris.h mpris::Mpris1Root core/mpris_root MprisRoot)
qt4_add_dbus_adaptor(SOURCES
dbus/org.freedesktop.MediaPlayer.tracklist.xml
core/mpris.h MPRIS core/mpris_tracklist MprisTrackList)
core/mpris.h mpris::Mpris1TrackList core/mpris_tracklist MprisTrackList)
# MPRIS 2.0 DBUS interfaces
qt4_add_dbus_adaptor(SOURCES
dbus/org.mpris.MediaPlayer2.Player.xml
core/mpris2.h MPRIS2 core/mpris2_player Mpris2Player)
core/mpris2.h mpris::Mpris2 core/mpris2_player Mpris2Player)
qt4_add_dbus_adaptor(SOURCES
dbus/org.mpris.MediaPlayer2.xml
core/mpris2.h MPRIS2 core/mpris2_root Mpris2Root)
core/mpris2.h mpris::Mpris2 core/mpris2_root Mpris2Root)
qt4_add_dbus_adaptor(SOURCES
dbus/org.mpris.MediaPlayer2.TrackList.xml
core/mpris2.h MPRIS2 core/mpris2_tracklist Mpris2TrackList)
core/mpris2.h mpris::Mpris2 core/mpris2_tracklist Mpris2TrackList)
# org.freedesktop.Notifications DBUS interface
qt4_add_dbus_interface(SOURCES
@ -583,8 +583,8 @@ if(NOT APPLE AND NOT WIN32)
dbus/udisksdevice)
# MPRIS source
list(APPEND SOURCES core/mpris.cpp core/mpris2.cpp)
list(APPEND HEADERS core/mpris.h core/mpris2.h)
list(APPEND SOURCES core/mpris_common.cpp core/mpris.cpp core/mpris2.cpp)
list(APPEND HEADERS core/mpris_common.h core/mpris.h core/mpris2.h)
# Wiimotedev interface classes
if(ENABLE_WIIMOTEDEV)
@ -683,6 +683,8 @@ list(APPEND OTHER_SOURCES
core/macglobalshortcutbackend.h
core/macglobalshortcutbackend.mm
core/modelfuturewatcher.h
core/mpris_common.cpp
core/mpris_common.h
core/mpris.cpp
core/mpris.h
core/mpris2.cpp

View File

@ -16,6 +16,7 @@
*/
#include "mpris.h"
#include "mpris_common.h"
#include <QCoreApplication>
#include <QDBusConnection>
@ -23,10 +24,271 @@
#include "core/mpris_player.h"
#include "core/mpris_root.h"
#include "core/mpris_tracklist.h"
#include "engines/enginebase.h"
#include "playlist/playlist.h"
#include "playlist/playlistmanager.h"
#include "playlist/playlistsequence.h"
namespace mpris {
Mpris1::Mpris1(Player* player, ArtLoader* art_loader, QObject* parent)
: QObject(parent)
{
qDBusRegisterMetaType<DBusStatus>();
qDBusRegisterMetaType<Version>();
QDBusConnection::sessionBus().registerService("org.mpris.clementine");
root_ = new Mpris1Root(player, this);
player_ = new Mpris1Player(player, this);
tracklist_ = new Mpris1TrackList(player, this);
connect(art_loader, SIGNAL(ArtLoaded(Song,QString)),
player_, SLOT(CurrentSongChanged(Song,QString)));
}
Mpris1Root::Mpris1Root(Player* player, QObject* parent)
: QObject(parent), player_(player) {
new MprisRoot(this);
QDBusConnection::sessionBus().registerObject("/", this);
}
Mpris1Player::Mpris1Player(Player* player, QObject* parent)
: QObject(parent), player_(player) {
new MprisPlayer(this);
QDBusConnection::sessionBus().registerObject("/Player", this);
connect(player->engine(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged()));
}
Mpris1TrackList::Mpris1TrackList(Player* player, QObject* parent)
: QObject(parent), player_(player) {
new MprisTrackList(this);
QDBusConnection::sessionBus().registerObject("/TrackList", this);
connect(player->playlists(), SIGNAL(PlaylistChanged()), SLOT(PlaylistChanged()));
}
void Mpris1TrackList::PlaylistChanged() {
emit TrackListChange(GetLength());
}
void Mpris1Player::EngineStateChanged() {
emit StatusChange(GetStatus());
emit CapsChange(GetCaps());
}
void Mpris1Player::CurrentSongChanged(const Song& song, const QString& art_uri) {
last_metadata_ = Mpris1::GetMetadata(song);
if (!art_uri.isEmpty()) {
AddMetadata("arturl", art_uri, &last_metadata_);
}
emit TrackChange(last_metadata_);
emit StatusChange(GetStatus());
emit CapsChange(GetCaps());
}
QString Mpris1Root::Identity() {
return QString("%1 %2").arg(
QCoreApplication::applicationName(),
QCoreApplication::applicationVersion());
}
Version Mpris1Root::MprisVersion() {
Version version;
version.major = 1;
version.minor = 0;
return version;
}
void Mpris1Root::Quit() {
qApp->quit();
}
void Mpris1Player::Pause() {
player_->Pause();
}
void Mpris1Player::Stop() {
player_->Stop();
}
void Mpris1Player::Prev() {
player_->Prev();
}
void Mpris1Player::Play() {
player_->Play();
}
void Mpris1Player::Next() {
player_->Next();
}
void Mpris1Player::Repeat(bool repeat) {
player_->Repeat(repeat);
}
DBusStatus Mpris1Player::GetStatus() const {
DBusStatus status;
switch (player_->GetState()) {
case Engine::Empty:
case Engine::Idle:
status.play = DBusStatus::Mpris_Stopped;
break;
case Engine::Playing:
status.play = DBusStatus::Mpris_Playing;
break;
case Engine::Paused:
status.play = DBusStatus::Mpris_Paused;
break;
}
PlaylistManager* playlists_ = player_->playlists();
PlaylistSequence::RepeatMode repeat_mode = playlists_->sequence()->repeat_mode();
status.random = playlists_->sequence()->shuffle_mode() == PlaylistSequence::Shuffle_Off ? 0 : 1;
status.repeat = repeat_mode == PlaylistSequence::Repeat_Track ? 1 : 0;
status.repeat_playlist = (repeat_mode == PlaylistSequence::Repeat_Album ||
repeat_mode == PlaylistSequence::Repeat_Playlist ||
repeat_mode == PlaylistSequence::Repeat_Track) ? 1 : 0;
return status;
}
void Mpris1Player::VolumeSet(int volume) {
player_->SetVolume(volume);
}
int Mpris1Player::VolumeGet() const {
return player_->VolumeGet();
}
void Mpris1Player::PositionSet(int pos) {
player_->Seek(pos/1000);
}
int Mpris1Player::PositionGet() const {
return player_->PositionGet();
}
QVariantMap Mpris1Player::GetMetadata() const {
return last_metadata_;
}
int Mpris1Player::GetCaps() const {
int caps = CAN_HAS_TRACKLIST;
Engine::State state = player_->GetState();
PlaylistItemPtr current_item = player_->GetCurrentItem();
PlaylistManager* playlists = player_->playlists();
if (playlists->active()->rowCount() != 0) {
caps |= CAN_PLAY;
}
if (current_item) {
caps |= CAN_PROVIDE_METADATA;
if (state == Engine::Playing && (!current_item->options() & PlaylistItem::PauseDisabled)) {
caps |= CAN_PAUSE;
}
if (state != Engine::Empty && current_item->Metadata().filetype() != Song::Type_Stream) {
caps |= CAN_SEEK;
}
}
if (playlists->active()->next_index() != -1 ||
playlists->active()->current_item_options() & PlaylistItem::ContainsMultipleTracks) {
caps |= CAN_GO_NEXT;
}
if (playlists->active()->previous_index() != -1) {
caps |= CAN_GO_PREV;
}
return caps;
}
void Mpris1Player::VolumeUp(int vol) {
player_->VolumeUp(vol);
}
void Mpris1Player::VolumeDown(int vol) {
player_->VolumeDown(vol);
}
void Mpris1Player::Mute() {
player_->Mute();
}
void Mpris1Player::ShowOSD() {
player_->ShowOSD();
}
int Mpris1TrackList::AddTrack(const QString& track, bool play) {
return player_->AddTrack(track, play);
}
void Mpris1TrackList::DelTrack(int index) {
player_->DelTrack(index);
}
int Mpris1TrackList::GetCurrentTrack() const {
return player_->GetCurrentTrack();
}
int Mpris1TrackList::GetLength() const {
return player_->playlists()->active()->rowCount();
}
QVariantMap Mpris1TrackList::GetMetadata(int pos) const {
return Mpris1::GetMetadata(player_->GetItemAt(pos)->Metadata());
}
void Mpris1TrackList::SetLoop(bool enable) {
player_->SetLoop(enable);
}
void Mpris1TrackList::SetRandom(bool enable) {
player_->SetRandom(enable);
}
void Mpris1TrackList::PlayTrack(int index) {
player_->PlayAt(index, Engine::Manual, true);
}
QVariantMap Mpris1::GetMetadata(const Song& song) {
QVariantMap ret;
AddMetadata("location", song.filename(), &ret);
AddMetadata("title", song.PrettyTitle(), &ret);
AddMetadata("artist", song.artist(), &ret);
AddMetadata("album", song.album(), &ret);
AddMetadata("time", song.length(), &ret);
AddMetadata("mtime", song.length() * 1000, &ret);
AddMetadata("tracknumber", song.track(), &ret);
AddMetadata("year", song.year(), &ret);
AddMetadata("genre", song.genre(), &ret);
AddMetadata("disc", song.disc(), &ret);
AddMetadata("comment", song.comment(), &ret);
AddMetadata("audio-bitrate", song.bitrate(), &ret);
AddMetadata("audio-samplerate", song.samplerate(), &ret);
AddMetadata("bpm", song.bpm(), &ret);
AddMetadata("composer", song.composer(), &ret);
AddMetadata("artUrl",
song.art_manual().isEmpty() ? song.art_automatic() : song.art_manual(), &ret);
if (song.rating() != -1.0) {
AddMetadata("rating", song.rating() * 5, &ret);
}
return ret;
}
} // namespace mpris
QDBusArgument& operator<< (QDBusArgument& arg, const Version& version) {
arg.beginStructure();
arg << version.major << version.minor;
@ -41,230 +303,22 @@ const QDBusArgument& operator>> (const QDBusArgument& arg, Version& version) {
return arg;
}
MPRIS::MPRIS(Player* player, QObject* parent)
: QObject(parent),
player_(player)
{
MprisRoot* mpris_root = new MprisRoot(this);
MprisPlayer* mpris_player = new MprisPlayer(this);
MprisTrackList* mpris_tracklist = new MprisTrackList(this);
QDBusConnection bus(QDBusConnection::sessionBus());
bus.registerService("org.mpris.clementine");
bus.registerObject("/", mpris_root, QDBusConnection::ExportAllContents);
bus.registerObject("/Player", mpris_player, QDBusConnection::ExportAllContents);
bus.registerObject("/TrackList", mpris_tracklist, QDBusConnection::ExportAllContents);
QDBusArgument& operator<< (QDBusArgument& arg, const DBusStatus& status) {
arg.beginStructure();
arg << status.play;
arg << status.random;
arg << status.repeat;
arg << status.repeat_playlist;
arg.endStructure();
return arg;
}
QString MPRIS::Identity() {
return QString("%1 %2").arg(
QCoreApplication::applicationName(),
QCoreApplication::applicationVersion());
}
Version MPRIS::MprisVersion() {
Version version;
version.major = 1;
version.minor = 0;
return version;
}
void MPRIS::Quit() {
qApp->quit();
}
void MPRIS::Pause() {
player_->Pause();
}
void MPRIS::Stop() {
player_->Stop();
}
void MPRIS::Prev() {
player_->Prev();
}
void MPRIS::Play() {
player_->Prev();
}
void MPRIS::Next() {
player_->Next();
}
void MPRIS::Repeat(bool repeat) {
player_->Repeat(repeat);
}
DBusStatus MPRIS::GetStatus() const {
DBusStatus status;
switch (player_->GetState()) {
case Engine::Empty:
case Engine::Idle:
status.play = DBusStatus::Mpris_Stopped;
break;
case Engine::Playing:
status.play = DBusStatus::Mpris_Playing;
break;
case Engine::Paused:
status.play = DBusStatus::Mpris_Paused;
break;
}
PlaylistManager* playlists_ = player_->GetPlaylists();
PlaylistSequence::RepeatMode repeat_mode = playlists_->sequence()->repeat_mode();
status.random = playlists_->sequence()->shuffle_mode() == PlaylistSequence::Shuffle_Off ? 0 : 1;
status.repeat = repeat_mode == PlaylistSequence::Repeat_Track ? 1 : 0;
status.repeat_playlist = (repeat_mode == PlaylistSequence::Repeat_Album ||
repeat_mode == PlaylistSequence::Repeat_Playlist ||
repeat_mode == PlaylistSequence::Repeat_Track) ? 1 : 0;
return status;
}
void MPRIS::VolumeSet(int volume) {
player_->SetVolume(volume);
}
int MPRIS::VolumeGet() const {
return player_->VolumeGet();
}
void MPRIS::PositionSet(int pos) {
player_->Seek(pos/1000);
}
int MPRIS::PositionGet() const {
return player_->PositionGet()*1000;
}
QVariantMap MPRIS::GetMetadata() const {
return GetMetadata(player_->GetCurrentItem());
}
int MPRIS::GetCaps() const {
int caps = CAN_HAS_TRACKLIST;
Engine::State state = player_->GetState();
boost::shared_ptr<PlaylistItem> current_item_ = player_->GetCurrentItem();
PlaylistManager* playlists_ = player_->GetPlaylists();
if (state == Engine::Paused) {
caps |= CAN_PLAY;
}
if (current_item_) {
caps |= CAN_PROVIDE_METADATA;
if (state == Engine::Playing && current_item_->options() & PlaylistItem::PauseDisabled) {
caps |= CAN_PAUSE;
}
if (state != Engine::Empty && current_item_->Metadata().filetype() != Song::Type_Stream) {
caps |= CAN_SEEK;
}
}
if (playlists_->active()->next_index() != -1 ||
playlists_->active()->current_item_options() & PlaylistItem::ContainsMultipleTracks) {
caps |= CAN_GO_NEXT;
}
if (playlists_->active()->previous_index() != -1) {
caps |= CAN_GO_PREV;
}
return caps;
}
void MPRIS::VolumeUp(int vol) {
player_->VolumeUp(vol);
}
void MPRIS::VolumeDown(int vol) {
player_->VolumeDown(vol);
}
void MPRIS::Mute() {
player_->Mute();
}
void MPRIS::ShowOSD() {
player_->ShowOSD();
}
int MPRIS::AddTrack(const QString& track, bool play) {
return player_->AddTrack(track, play);
}
void MPRIS::DelTrack(int index) {
player_->DelTrack(index);
}
int MPRIS::GetCurrentTrack() const {
return player_->GetCurrentTrack();
}
int MPRIS::GetLength() const {
return player_->GetLength();
}
QVariantMap MPRIS::GetMetadata(int pos) const {
return GetMetadata(player_->GetItemAt(pos));
}
void MPRIS::SetLoop(bool enable) {
player_->SetLoop(enable);
}
void MPRIS::SetRandom(bool enable) {
player_->SetRandom(enable);
}
void MPRIS::PlayTrack(int index) {
player_->PlayAt(index, Engine::Manual, true);
}
void MPRIS::EmitCapsChange(int param) {
emit CapsChange(param);
}
void MPRIS::EmitTrackChange(QVariantMap param) {
emit TrackChange(param);
}
void MPRIS::EmitStatusChange(DBusStatus param) {
emit StatusChange(param);
}
void MPRIS::EmitTrackListChange(int i) {
emit TrackListChange(i);
}
QVariantMap MPRIS::GetMetadata(PlaylistItemPtr item) const {
using metadata::AddMetadata;
QVariantMap ret;
if (!item)
return ret;
Song song = item->Metadata();
AddMetadata("location", item->Url().toString(), &ret);
AddMetadata("title", song.PrettyTitle(), &ret);
AddMetadata("artist", song.artist(), &ret);
AddMetadata("album", song.album(), &ret);
AddMetadata("time", song.length(), &ret);
AddMetadata("tracknumber", song.track(), &ret);
AddMetadata("year", song.year(), &ret);
AddMetadata("genre", song.genre(), &ret);
AddMetadata("disc", song.disc(), &ret);
AddMetadata("comment", song.comment(), &ret);
AddMetadata("audio-bitrate", song.bitrate(), &ret);
AddMetadata("audio-samplerate", song.samplerate(), &ret);
AddMetadata("bpm", song.bpm(), &ret);
AddMetadata("composer", song.composer(), &ret);
AddMetadata("artUrl",
song.art_manual().isEmpty() ? song.art_automatic() : song.art_manual(), &ret);
if (song.rating() != -1.0) {
AddMetadata("rating", song.rating(), &ret);
}
return ret;
const QDBusArgument& operator>> (const QDBusArgument& arg, DBusStatus& status) {
arg.beginStructure();
arg >> status.play;
arg >> status.random;
arg >> status.repeat;
arg >> status.repeat_playlist;
arg.endStructure();
return arg;
}

View File

@ -26,7 +26,6 @@
class Player;
struct DBusStatus { // From Amarok.
int play; // Playing = 0, Paused = 1, Stopped = 2
int random; // Linearly = 0, Randomly = 1
@ -41,11 +40,21 @@ struct DBusStatus { // From Amarok.
};
Q_DECLARE_METATYPE(DBusStatus);
QDBusArgument& operator <<(QDBusArgument& arg, const DBusStatus& status);
const QDBusArgument& operator >>(const QDBusArgument& arg, DBusStatus& status);
struct Version {
quint16 minor;
quint16 major;
};
Q_DECLARE_METATYPE(Version)
Q_DECLARE_METATYPE(Version);
QDBusArgument& operator <<(QDBusArgument& arg, const Version& version);
const QDBusArgument& operator >>(const QDBusArgument& arg, Version& version);
namespace mpris {
enum DBusCaps {
NONE = 0,
@ -59,56 +68,48 @@ enum DBusCaps {
};
#ifdef Q_WS_X11
# include <QDBusArgument>
QDBusArgument& operator<< (QDBusArgument& arg, const DBusStatus& status);
const QDBusArgument& operator>> (const QDBusArgument& arg, DBusStatus& status);
#endif
class ArtLoader;
class Mpris1Root;
class Mpris1Player;
class Mpris1TrackList;
namespace metadata {
inline void AddMetadata(const QString& key, const QString& metadata, QVariantMap* map) {
if (!metadata.isEmpty()) {
(*map)[key] = metadata;
}
}
inline void AddMetadata(const QString& key, int metadata, QVariantMap* map) {
if (metadata > 0) {
(*map)[key] = metadata;
}
}
inline void AddMetadata(const QString& key, const QDateTime& metadata, QVariantMap* map) {
if (metadata.isValid()) {
(*map)[key] = metadata;
}
}
inline void AddMetadata(const QString &key, const QStringList& metadata, QVariantMap *map) {
if (!metadata.isEmpty()) {
(*map)[key] = metadata;
}
}
} // namespace metadata
QDBusArgument& operator<< (QDBusArgument& arg, const Version& version);
const QDBusArgument& operator>> (const QDBusArgument& arg, Version& version);
class MPRIS : public QObject {
class Mpris1 : public QObject {
Q_OBJECT
public:
// Root interface
MPRIS(Player* player, QObject* parent);
Mpris1(Player* player, ArtLoader* art_loader, QObject* parent);
static QVariantMap GetMetadata(const Song& song);
private:
Mpris1Root* root_;
Mpris1Player* player_;
Mpris1TrackList* tracklist_;
};
class Mpris1Root : public QObject {
Q_OBJECT
public:
Mpris1Root(Player* player, QObject* parent);
QString Identity();
void Quit();
Version MprisVersion();
// Player Interface
private:
Player* player_;
};
class Mpris1Player : public QObject {
Q_OBJECT
public:
Mpris1Player(Player* player, QObject* parent);
void Pause();
void Stop();
void Prev();
@ -121,16 +122,38 @@ public:
void PositionSet(int pos);
int PositionGet() const;
QVariantMap GetMetadata() const;
QVariantMap GetMetadata(PlaylistItemPtr item) const;
int GetCaps() const;
// Amarok Extensions for Player
// Amarok extensions
void VolumeUp(int vol);
void VolumeDown(int vol);
void Mute();
void ShowOSD();
// Tracklist Interface
public slots:
void CurrentSongChanged(const Song& song, const QString& art_uri);
signals:
void CapsChange(int);
void TrackChange(const QVariantMap&);
void StatusChange(DBusStatus);
private slots:
void EngineStateChanged();
private:
Player* player_;
QVariantMap last_metadata_;
};
class Mpris1TrackList : public QObject {
Q_OBJECT
public:
Mpris1TrackList(Player* player, QObject* parent);
int AddTrack(const QString&, bool);
void DelTrack(int index);
int GetCurrentTrack() const;
@ -139,27 +162,19 @@ public:
void SetLoop(bool enable);
void SetRandom(bool enable);
// Amarok extension.
// Amarok extension
void PlayTrack(int index);
// Signals Emitters
void EmitCapsChange(int param);
void EmitTrackChange(QVariantMap param);
void EmitStatusChange(DBusStatus);
void EmitTrackListChange(int i);
signals:
void CapsChange(int);
void TrackChange(QVariantMap);
void StatusChange(DBusStatus);
// TrackList
void TrackListChange(int i);
private slots:
void PlaylistChanged();
private:
Player* player_;
};
} // namespace mpris
#endif // MPRIS_H

View File

@ -16,13 +16,14 @@
*/
#include "config.h"
#include "mpris_common.h"
#include "mpris.h"
#include "mpris2.h"
#include "core/albumcoverloader.h"
#include "core/mpris2_player.h"
#include "core/mpris2_root.h"
#include "core/mpris2_tracklist.h"
#include "core/player.h"
#include "engines/enginebase.h"
#include "playlist/playlistmanager.h"
#include "playlist/playlistsequence.h"
#include "ui/mainwindow.h"
@ -34,20 +35,18 @@
# include <qindicateserver.h>
#endif
const char* MPRIS2::kMprisObjectPath = "/org/mpris/MediaPlayer2";
const char* MPRIS2::kServiceName = "org.mpris.MediaPlayer2.clementine";
const char* MPRIS2::kFreedesktopPath = "org.freedesktop.DBus.Properties";
namespace mpris {
MPRIS2::MPRIS2(MainWindow* main_window, Player* player, QObject* parent)
const char* Mpris2::kMprisObjectPath = "/org/mpris/MediaPlayer2";
const char* Mpris2::kServiceName = "org.mpris.MediaPlayer2.clementine";
const char* Mpris2::kFreedesktopPath = "org.freedesktop.DBus.Properties";
Mpris2::Mpris2(MainWindow* main_window, Player* player, ArtLoader* art_loader,
QObject* parent)
: QObject(parent),
cover_loader_(new BackgroundThreadImplementation<AlbumCoverLoader, AlbumCoverLoader>(this)),
art_request_id_(0),
ui_(main_window),
player_(player)
{
cover_loader_->Start();
connect(cover_loader_, SIGNAL(Initialised()), SLOT(Initialised()));
new Mpris2Root(this);
new Mpris2TrackList(this);
new Mpris2Player(this);
@ -61,9 +60,22 @@ MPRIS2::MPRIS2(MainWindow* main_window, Player* player, QObject* parent)
indicate_server->setDesktopFile(DesktopEntry());
indicate_server->show();
#endif
connect(art_loader, SIGNAL(ArtLoaded(Song,QString)), SLOT(ArtLoaded(Song,QString)));
connect(player->engine(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged()));
connect(player, SIGNAL(VolumeChanged(int)), SLOT(VolumeChanged()));
}
void MPRIS2::emitNotification(const QString& name, const QVariant& val) {
void Mpris2::EngineStateChanged() {
EmitNotification("PlaybackStatus");
}
void Mpris2::VolumeChanged() {
EmitNotification("Volume");
}
void Mpris2::EmitNotification(const QString& name, const QVariant& val) {
QDBusMessage msg = QDBusMessage::createSignal(
kMprisObjectPath, kFreedesktopPath, "PropertiesChanged");
QVariantMap map;
@ -76,7 +88,7 @@ void MPRIS2::emitNotification(const QString& name, const QVariant& val) {
QDBusConnection::sessionBus().send(msg);
}
void MPRIS2::emitNotification(const QString& name) {
void Mpris2::EmitNotification(const QString& name) {
QVariant value;
if (name == "PlaybackStatus") value = PlaybackStatus();
else if (name == "LoopStatus") value = LoopStatus();
@ -86,30 +98,30 @@ void MPRIS2::emitNotification(const QString& name) {
else if (name == "Position") value = Position();
if (value.isValid())
emitNotification(name, value);
EmitNotification(name, value);
}
//------------------Root Interface--------------------------//
bool MPRIS2::CanQuit() const {
bool Mpris2::CanQuit() const {
return true;
}
bool MPRIS2::CanRaise() const {
bool Mpris2::CanRaise() const {
return true;
}
bool MPRIS2::HasTrackList() const {
bool Mpris2::HasTrackList() const {
return true;
}
QString MPRIS2::Identity() const {
QString Mpris2::Identity() const {
return QString("%1 %2").arg(
QCoreApplication::applicationName(),
QCoreApplication::applicationVersion());
}
QString MPRIS2::DesktopEntry() const {
QString Mpris2::DesktopEntry() const {
QStringList xdg_data_dirs = QString(getenv("XDG_DATA_DIRS")).split(":");
xdg_data_dirs.append("/usr/local/share/");
xdg_data_dirs.append("/usr/share/");
@ -123,7 +135,7 @@ QString MPRIS2::DesktopEntry() const {
return QString();
}
QStringList MPRIS2::SupportedUriSchemes() const {
QStringList Mpris2::SupportedUriSchemes() const {
static QStringList res = QStringList()
<< "file"
<< "http"
@ -133,7 +145,7 @@ QStringList MPRIS2::SupportedUriSchemes() const {
return res;
}
QStringList MPRIS2::SupportedMimeTypes() const {
QStringList Mpris2::SupportedMimeTypes() const {
static QStringList res = QStringList()
<< "application/ogg"
<< "application/x-ogg"
@ -163,16 +175,16 @@ QStringList MPRIS2::SupportedMimeTypes() const {
return res;
}
void MPRIS2::Raise() {
void Mpris2::Raise() {
ui_->show();
ui_->activateWindow();
}
void MPRIS2::Quit() {
void Mpris2::Quit() {
qApp->quit();
}
QString MPRIS2::PlaybackStatus() const {
QString Mpris2::PlaybackStatus() const {
switch (player_->GetState()) {
case Engine::Playing: return "Playing";
case Engine::Paused: return "Paused";
@ -180,8 +192,8 @@ QString MPRIS2::PlaybackStatus() const {
}
}
QString MPRIS2::LoopStatus() const {
switch (player_->GetPlaylists()->sequence()->repeat_mode()) {
QString Mpris2::LoopStatus() const {
switch (player_->playlists()->sequence()->repeat_mode()) {
case PlaylistSequence::Repeat_Album:
case PlaylistSequence::Repeat_Playlist: return "Playlist";
case PlaylistSequence::Repeat_Track: return "Track";
@ -189,7 +201,7 @@ QString MPRIS2::LoopStatus() const {
}
}
void MPRIS2::SetLoopStatus(const QString& value) {
void Mpris2::SetLoopStatus(const QString& value) {
if (value == "None") {
player_->SetLoop(PlaylistSequence::Repeat_Off);
} else if (value == "Track") {
@ -197,60 +209,40 @@ void MPRIS2::SetLoopStatus(const QString& value) {
} else if (value == "Playlist") {
player_->SetLoop(PlaylistSequence::Repeat_Playlist);
}
emitNotification("LoopStatus", value);
EmitNotification("LoopStatus", value);
}
double MPRIS2::Rate() const {
double Mpris2::Rate() const {
return 1.0;
}
void MPRIS2::SetRate(double) {
void Mpris2::SetRate(double) {
// Do nothing
}
bool MPRIS2::Shuffle() const {
return player_->GetPlaylists()->sequence()->shuffle_mode() !=
bool Mpris2::Shuffle() const {
return player_->playlists()->sequence()->shuffle_mode() !=
PlaylistSequence::Shuffle_Off;
}
void MPRIS2::SetShuffle(bool value) {
void Mpris2::SetShuffle(bool value) {
player_->SetRandom(value);
emitNotification("Shuffle", value);
EmitNotification("Shuffle", value);
}
QVariantMap MPRIS2::Metadata() const {
QVariantMap Mpris2::Metadata() const {
return last_metadata_;
}
void MPRIS2::UpdateMetadata(PlaylistItemPtr item) {
void Mpris2::ArtLoaded(const Song& song, const QString& art_uri) {
last_metadata_ = QVariantMap();
// Load the cover art
art_request_item_ = item;
art_request_id_ = cover_loader_->Worker()->LoadImageAsync(item->Metadata());
}
void MPRIS2::Initialised() {
cover_loader_->Worker()->SetPadOutputImage(true);
cover_loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png"));
connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)),
SLOT(TempArtLoaded(quint64,QImage)));
}
void MPRIS2::TempArtLoaded(quint64 id, const QImage& image) {
if (id != art_request_id_ || !art_request_item_)
return;
art_request_id_ = 0;
last_metadata_ = QVariantMap();
Song song = art_request_item_->Metadata();
QString track_id = QString("/org/mpris/MediaPlayer2/Track/%1").
arg(QString::number(player_->GetCurrentTrack()));
using metadata::AddMetadata;
using mpris::AddMetadata;
AddMetadata("mpris:trackid", track_id, &last_metadata_);
AddMetadata("xesam:url", art_request_item_->Url().toString(), &last_metadata_);
AddMetadata("xesam:url", song.filename(), &last_metadata_);
AddMetadata("xesam:title", song.PrettyTitle(), &last_metadata_);
AddMetadata("xesam:artist", QStringList() << song.artist(), &last_metadata_);
AddMetadata("xesam:album", song.album(), &last_metadata_);
@ -264,132 +256,130 @@ void MPRIS2::TempArtLoaded(quint64 id, const QImage& image) {
AddMetadata("xesam:audioBPM", song.bpm(), &last_metadata_);
AddMetadata("xesam:composer", song.composer(), &last_metadata_);
if (!image.isNull()) {
temp_art_.reset(new QTemporaryFile(QDir::tempPath() + "/clementine-art-XXXXXX.jpg"));
temp_art_->open();
image.save(temp_art_->fileName(), "JPEG");
AddMetadata("mpris:artUrl", "file://" + temp_art_->fileName(), &last_metadata_);
if (!art_uri.isEmpty()) {
AddMetadata("mpris:artUrl", art_uri, &last_metadata_);
}
emitNotification("Metadata", last_metadata_);
art_request_item_.reset();
EmitNotification("Metadata", last_metadata_);
}
double MPRIS2::Volume() const {
double Mpris2::Volume() const {
return player_->VolumeGet() / 100;
}
void MPRIS2::SetVolume(double value) {
void Mpris2::SetVolume(double value) {
player_->SetVolume(value * 100);
emitNotification("Volume",value);
EmitNotification("Volume",value);
}
qlonglong MPRIS2::Position() const {
qlonglong Mpris2::Position() const {
return player_->PositionGet() * 1e6;
}
double MPRIS2::MaximumRate() const {
double Mpris2::MaximumRate() const {
return 1.0;
}
double MPRIS2::MinimumRate() const {
double Mpris2::MinimumRate() const {
return 1.0;
}
bool MPRIS2::CanGoNext() const {
bool Mpris2::CanGoNext() const {
return true;
}
bool MPRIS2::CanGoPrevious() const {
bool Mpris2::CanGoPrevious() const {
return true;
}
bool MPRIS2::CanPlay() const {
bool Mpris2::CanPlay() const {
return true;
}
bool MPRIS2::CanPause() const {
bool Mpris2::CanPause() const {
return true;
}
bool MPRIS2::CanSeek() const {
bool Mpris2::CanSeek() const {
return true;
}
bool MPRIS2::CanControl() const {
bool Mpris2::CanControl() const {
return true;
}
void MPRIS2::Next() {
void Mpris2::Next() {
player_->Next();
emitNotification("PlaybackStatus",PlaybackStatus());
emitNotification("Metadata",Metadata());
EmitNotification("PlaybackStatus",PlaybackStatus());
EmitNotification("Metadata",Metadata());
}
void MPRIS2::Previous() {
void Mpris2::Previous() {
player_->Previous();
emitNotification("PlaybackStatus",PlaybackStatus());
emitNotification("Metadata",Metadata());
EmitNotification("PlaybackStatus",PlaybackStatus());
EmitNotification("Metadata",Metadata());
}
void MPRIS2::Pause() {
void Mpris2::Pause() {
player_->Pause();
emitNotification("PlaybackStatus",PlaybackStatus());
emitNotification("Metadata",Metadata());
EmitNotification("PlaybackStatus",PlaybackStatus());
EmitNotification("Metadata",Metadata());
}
void MPRIS2::PlayPause() {
void Mpris2::PlayPause() {
player_->PlayPause();
emitNotification("PlaybackStatus",PlaybackStatus());
emitNotification("Metadata",Metadata());
EmitNotification("PlaybackStatus",PlaybackStatus());
EmitNotification("Metadata",Metadata());
}
void MPRIS2::Stop() {
void Mpris2::Stop() {
player_->Stop();
emitNotification("PlaybackStatus",PlaybackStatus());
emitNotification("Metadata",Metadata());
EmitNotification("PlaybackStatus",PlaybackStatus());
EmitNotification("Metadata",Metadata());
}
void MPRIS2::Play() {
void Mpris2::Play() {
player_->Play();
emitNotification("PlaybackStatus",PlaybackStatus());
emitNotification("Metadata",Metadata());
EmitNotification("PlaybackStatus",PlaybackStatus());
EmitNotification("Metadata",Metadata());
}
void MPRIS2::Seek(qlonglong offset) {
void Mpris2::Seek(qlonglong offset) {
player_->Seek(offset*1e6);
}
void MPRIS2::SetPosition(const QDBusObjectPath& trackId, qlonglong offset) {
void Mpris2::SetPosition(const QDBusObjectPath& trackId, qlonglong offset) {
//TODO
}
void MPRIS2::OpenUri(const QString &uri) {
void Mpris2::OpenUri(const QString &uri) {
player_->AddTrack(uri,true);
}
TrackIds MPRIS2::Tracks() const {
TrackIds Mpris2::Tracks() const {
//TODO
return TrackIds();
}
bool MPRIS2::CanEditTracks() const {
bool Mpris2::CanEditTracks() const {
return false;
}
TrackMetadata MPRIS2::GetTracksMetadata(const TrackIds &tracks) const {
TrackMetadata Mpris2::GetTracksMetadata(const TrackIds &tracks) const {
//TODO
return TrackMetadata();
}
void MPRIS2::AddTrack(const QString &uri, const QDBusObjectPath &afterTrack, bool setAsCurrent) {
void Mpris2::AddTrack(const QString &uri, const QDBusObjectPath &afterTrack, bool setAsCurrent) {
//TODO
}
void MPRIS2::RemoveTrack(const QDBusObjectPath &trackId) {
void Mpris2::RemoveTrack(const QDBusObjectPath &trackId) {
//TODO
}
void MPRIS2::GoTo(const QDBusObjectPath &trackId) {
void Mpris2::GoTo(const QDBusObjectPath &trackId) {
//TODO
}
} // namespace mpris

View File

@ -18,7 +18,6 @@
#ifndef MPRIS2_H
#define MPRIS2_H
#include "core/backgroundthread.h"
#include "playlist/playlistitem.h"
#include <QMetaObject>
@ -27,17 +26,18 @@
#include <boost/scoped_ptr.hpp>
class AlbumCoverLoader;
class MainWindow;
class Player;
class QTemporaryFile;
typedef QList<QVariantMap> TrackMetadata;
typedef QList<QDBusObjectPath> TrackIds;
Q_DECLARE_METATYPE(TrackMetadata)
class MPRIS2 : public QObject {
namespace mpris {
class ArtLoader;
class Mpris2 : public QObject {
Q_OBJECT
//org.mpris.MediaPlayer2 MPRIS 2.0 Root interface
@ -71,9 +71,7 @@ class MPRIS2 : public QObject {
Q_PROPERTY( bool CanEditTracks READ CanEditTracks )
public:
MPRIS2(MainWindow* main_window, Player* player, QObject* parent);
void emitNotification(const QString& name);
void emitNotification(const QString& name, const QVariant& val);
Mpris2(MainWindow* main_window, Player* player, ArtLoader* art_loader, QObject* parent);
// Root Properties
bool CanQuit() const;
@ -130,9 +128,6 @@ public:
void RemoveTrack(const QDBusObjectPath& trackId);
void GoTo(const QDBusObjectPath& trackId);
public slots:
void UpdateMetadata(PlaylistItemPtr item);
signals:
// Player
void Seeked(qlonglong position);
@ -144,23 +139,25 @@ signals:
void TrackMetadataChanged(const QDBusObjectPath& trackId, const TrackMetadata& metadata);
private slots:
void Initialised();
void TempArtLoaded(quint64 id, const QImage& image);
void ArtLoaded(const Song& song, const QString& art_uri);
void EngineStateChanged();
void VolumeChanged();
private:
void EmitNotification(const QString& name);
void EmitNotification(const QString& name, const QVariant& val);
private:
static const char* kMprisObjectPath;
static const char* kServiceName;
static const char* kFreedesktopPath;
boost::scoped_ptr<QTemporaryFile> temp_art_;
BackgroundThread<AlbumCoverLoader>* cover_loader_;
quint64 art_request_id_;
PlaylistItemPtr art_request_item_;
QVariantMap last_metadata_;
MainWindow* ui_;
Player* player_;
};
} // namespace mpris
#endif

69
src/core/mpris_common.cpp Normal file
View File

@ -0,0 +1,69 @@
/* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "albumcoverloader.h"
#include "mpris_common.h"
#include <QDir>
#include <QTemporaryFile>
namespace mpris {
ArtLoader::ArtLoader(QObject* parent)
: QObject(parent),
cover_loader_(new BackgroundThreadImplementation<AlbumCoverLoader, AlbumCoverLoader>(this)),
id_(0)
{
cover_loader_->Start();
connect(cover_loader_, SIGNAL(Initialised()), SLOT(Initialised()));
}
ArtLoader::~ArtLoader() {
}
void ArtLoader::Initialised() {
cover_loader_->Worker()->SetPadOutputImage(true);
cover_loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png"));
connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)),
SLOT(TempArtLoaded(quint64,QImage)));
}
void ArtLoader::LoadArt(const Song& song) {
last_song_ = song;
id_ = cover_loader_->Worker()->LoadImageAsync(song);
}
void ArtLoader::TempArtLoaded(quint64 id, const QImage& image) {
if (id != id_)
return;
id_ = 0;
QString uri;
if (!image.isNull()) {
temp_art_.reset(new QTemporaryFile(QDir::tempPath() + "/clementine-art-XXXXXX.jpg"));
temp_art_->open();
image.save(temp_art_->fileName(), "JPEG");
uri = "file://" + temp_art_->fileName();
}
emit ArtLoaded(last_song_, uri);
}
} // namespace mpris

82
src/core/mpris_common.h Normal file
View File

@ -0,0 +1,82 @@
/* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MPRIS_COMMON_H
#define MPRIS_COMMON_H
#include "backgroundthread.h"
#include "song.h"
#include <QDateTime>
#include <QObject>
#include <QStringList>
#include <QVariantMap>
#include <boost/scoped_ptr.hpp>
class AlbumCoverLoader;
class QImage;
class QTemporaryFile;
namespace mpris {
class ArtLoader : public QObject {
Q_OBJECT
public:
ArtLoader(QObject* parent);
~ArtLoader();
public slots:
void LoadArt(const Song& song);
signals:
void ArtLoaded(const Song& song, const QString& uri);
private slots:
void Initialised();
void TempArtLoaded(quint64 id, const QImage& image);
private:
boost::scoped_ptr<QTemporaryFile> temp_art_;
BackgroundThread<AlbumCoverLoader>* cover_loader_;
quint64 id_;
Song last_song_;
};
inline void AddMetadata(const QString& key, const QString& metadata, QVariantMap* map) {
if (!metadata.isEmpty()) (*map)[key] = metadata;
}
inline void AddMetadata(const QString& key, int metadata, QVariantMap* map) {
if (metadata > 0) (*map)[key] = metadata;
}
inline void AddMetadata(const QString& key, const QDateTime& metadata, QVariantMap* map) {
if (metadata.isValid()) (*map)[key] = metadata;
}
inline void AddMetadata(const QString &key, const QStringList& metadata, QVariantMap *map) {
if (!metadata.isEmpty()) (*map)[key] = metadata;
}
} // namespace mpris
#endif // MPRIS_COMMON_H

View File

@ -37,6 +37,7 @@
#endif
#ifdef Q_WS_X11
# include "mpris_common.h"
# include "mpris.h"
# include "mpris2.h"
# include <QDBusConnection>
@ -50,32 +51,11 @@
using boost::shared_ptr;
#ifdef Q_WS_X11
QDBusArgument& operator<< (QDBusArgument& arg, const DBusStatus& status) {
arg.beginStructure();
arg << status.play;
arg << status.random;
arg << status.repeat;
arg << status.repeat_playlist;
arg.endStructure();
return arg;
}
const QDBusArgument& operator>> (const QDBusArgument& arg, DBusStatus& status) {
arg.beginStructure();
arg >> status.play;
arg >> status.random;
arg >> status.repeat;
arg >> status.repeat_playlist;
arg.endStructure();
return arg;
}
#endif
Player::Player(MainWindow* main_window, PlaylistManager* playlists,
LastFMService* lastfm, Engine::Type engine, QObject* parent)
: QObject(parent),
mpris_(NULL),
mpris1_(NULL),
mpris2_(NULL),
playlists_(playlists),
lastfm_(lastfm),
@ -85,15 +65,20 @@ Player::Player(MainWindow* main_window, PlaylistManager* playlists,
{
#ifdef Q_WS_X11
// MPRIS DBus interface.
qDBusRegisterMetaType<DBusStatus>();
qDBusRegisterMetaType<Version>();
qDBusRegisterMetaType<QImage>();
qDBusRegisterMetaType<TrackMetadata>();
qDBusRegisterMetaType<TrackIds>();
// Loads album art and saves it to a file in /tmp for MPRIS clients to use
mpris::ArtLoader* art_loader = new mpris::ArtLoader(this);
connect(playlists, SIGNAL(CurrentSongChanged(Song)),
art_loader, SLOT(LoadArt(Song)));
//MPRIS 1.0 implementation
mpris_ = new MPRIS(this, this);
mpris1_ = new mpris::Mpris1(this, art_loader, this);
//MPRIS 2.0 implementation
mpris2_ = new MPRIS2(main_window, this, this);
mpris2_ = new mpris::Mpris2(main_window, this, art_loader, this);
#endif
settings_.beginGroup("Player");
@ -101,7 +86,6 @@ Player::Player(MainWindow* main_window, PlaylistManager* playlists,
SetVolume(settings_.value("volume", 50).toInt());
connect(engine_.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString)));
}
Player::~Player() {
@ -268,10 +252,6 @@ void Player::PlayPause() {
break;
}
}
#ifdef Q_WS_X11
mpris2_->emitNotification("PlaybackStatus");
#endif
}
void Player::Stop() {
@ -298,13 +278,6 @@ void Player::EngineStateChanged(Engine::State state) {
case Engine::Empty:
case Engine::Idle: emit Stopped(); break;
}
#ifdef Q_WS_X11
mpris_->EmitStatusChange(mpris_->GetStatus());
mpris_->EmitCapsChange(mpris_->GetCaps());
mpris2_->emitNotification("PlaybackStatus");
mpris2_->emitNotification("Metadata");
#endif
}
void Player::SetVolume(int value) {
@ -316,9 +289,6 @@ void Player::SetVolume(int value) {
if (volume != old_volume){
emit VolumeChanged(volume);
#ifdef Q_WS_X11
mpris2_->emitNotification("Volume");
#endif
}
}
@ -353,22 +323,10 @@ void Player::PlayAt(int index, Engine::TrackChangeType change, bool reshuffle) {
if (lastfm_->IsScrobblingEnabled())
lastfm_->NowPlaying(current_item_->Metadata());
}
#ifdef Q_WS_X11
mpris_->EmitCapsChange(mpris_->GetCaps());
mpris2_->emitNotification("PlaybackStatus");
mpris2_->emitNotification("Metadata");
#endif
}
void Player::CurrentMetadataChanged(const Song& metadata) {
lastfm_->NowPlaying(metadata);
#ifdef Q_WS_X11
PlaylistItemPtr item = playlists_->active()->current_item();
mpris_->EmitTrackChange(mpris_->GetMetadata(item));
mpris2_->UpdateMetadata(item);
#endif
}
void Player::Seek(int seconds) {
@ -497,10 +455,6 @@ int Player::GetCurrentTrack() const {
return playlists_->active()->current_index();
}
int Player::GetLength() const {
return playlists_->active()->rowCount();
}
void Player::SetLoop(bool enable) {
playlists_->active()->sequence()->SetRepeatMode(
enable ? PlaylistSequence::Repeat_Playlist : PlaylistSequence::Repeat_Off);
@ -511,12 +465,6 @@ void Player::SetRandom(bool enable) {
enable ? PlaylistSequence::Shuffle_All : PlaylistSequence::Shuffle_Off);
}
void Player::PlaylistChanged() {
#ifdef Q_WS_X11
mpris_->EmitTrackListChange(GetLength());
#endif
}
void Player::TrackAboutToEnd() {
if (engine_->is_autocrossfade_enabled()) {
// Crossfade is on, so just start playing the next track. The current one

View File

@ -32,8 +32,11 @@ class PlaylistManager;
class Settings;
class LastFMService;
class MainWindow;
class MPRIS;
class MPRIS2;
namespace mpris {
class Mpris1;
class Mpris2;
}
#ifdef Q_WS_X11
@ -53,13 +56,13 @@ class Player : public QObject {
EngineBase* CreateEngine(Engine::Type engine);
void Init();
EngineBase* GetEngine() { return engine_.get(); }
EngineBase* engine() const { return engine_.get(); }
Engine::State GetState() const;
int GetVolume() const;
PlaylistItemPtr GetCurrentItem() const { return current_item_; }
PlaylistItemPtr GetItemAt(int pos) const;
PlaylistManager* GetPlaylists() {return playlists_; }
PlaylistManager* playlists() const { return playlists_; }
public slots:
void ReloadSettings();
@ -83,8 +86,6 @@ class Player : public QObject {
void HandleSpecialLoad(const PlaylistItem::SpecialLoadResult& result);
void CurrentMetadataChanged(const Song& metadata);
void PlaylistChanged();
// MPRIS /Player
void Mute();
void Pause();
@ -104,7 +105,6 @@ class Player : public QObject {
int AddTrack(const QString&, bool);
void DelTrack(int index);
int GetCurrentTrack() const;
int GetLength() const;
void SetLoop(bool enable);
void SetRandom(bool enable);
@ -131,8 +131,8 @@ class Player : public QObject {
void NextInternal(Engine::TrackChangeType);
private:
MPRIS* mpris_;
MPRIS2* mpris2_;
mpris::Mpris1* mpris1_;
mpris::Mpris2* mpris2_;
PlaylistManager* playlists_;
LastFMService* lastfm_;

View File

@ -204,12 +204,12 @@ MainWindow::MainWindow(Engine::Type engine, QWidget *parent)
// Start initialising the player
player_->Init();
background_streams_ = new BackgroundStreams(player_->GetEngine(), this);
background_streams_ = new BackgroundStreams(player_->engine(), this);
background_streams_->LoadStreams();
#ifdef HAVE_GSTREAMER
if (qobject_cast<GstEngine*>(player_->GetEngine()) == NULL) {
if (qobject_cast<GstEngine*>(player_->engine()) == NULL) {
ui_->action_transcode->setEnabled(false);
}
#else // HAVE_GSTREAMER
@ -368,7 +368,6 @@ MainWindow::MainWindow(Engine::Type engine, QWidget *parent)
connect(playlists_, SIGNAL(CurrentSongChanged(Song)), SLOT(SongChanged(Song)));
connect(playlists_, SIGNAL(CurrentSongChanged(Song)), osd_, SLOT(SongChanged(Song)));
connect(playlists_, SIGNAL(CurrentSongChanged(Song)), player_, SLOT(CurrentMetadataChanged(Song)));
connect(playlists_, SIGNAL(PlaylistChanged()), player_, SLOT(PlaylistChanged()));
connect(playlists_, SIGNAL(EditingFinished(QModelIndex)), SLOT(PlaylistEditFinished(QModelIndex)));
connect(playlists_, SIGNAL(Error(QString)), SLOT(ShowErrorDialog(QString)));
connect(playlists_, SIGNAL(SummaryTextChanged(QString)), ui_->playlist_summary, SLOT(setText(QString)));
@ -518,16 +517,16 @@ MainWindow::MainWindow(Engine::Type engine, QWidget *parent)
ConnectInfoView(artist_info_view_);
// Analyzer
ui_->analyzer->SetEngine(player_->GetEngine());
ui_->analyzer->SetEngine(player_->engine());
ui_->analyzer->SetActions(ui_->action_visualisations);
// Equalizer
connect(equalizer_.get(), SIGNAL(ParametersChanged(int,QList<int>)),
player_->GetEngine(), SLOT(SetEqualizerParameters(int,QList<int>)));
player_->engine(), SLOT(SetEqualizerParameters(int,QList<int>)));
connect(equalizer_.get(), SIGNAL(EnabledChanged(bool)),
player_->GetEngine(), SLOT(SetEqualizerEnabled(bool)));
player_->GetEngine()->SetEqualizerEnabled(equalizer_->is_enabled());
player_->GetEngine()->SetEqualizerParameters(
player_->engine(), SLOT(SetEqualizerEnabled(bool)));
player_->engine()->SetEqualizerEnabled(equalizer_->is_enabled());
player_->engine()->SetEqualizerParameters(
equalizer_->preamp_value(), equalizer_->gain_values());
// Statusbar widgets
@ -791,8 +790,8 @@ void MainWindow::TrackSkipped(PlaylistItemPtr item) {
// the database.
if (item && item->IsLocalLibraryItem() && !playlists_->active()->has_scrobbled()) {
Song song = item->Metadata();
const int position = player_->GetEngine()->position();
const int length = player_->GetEngine()->length();
const int position = player_->engine()->position();
const int length = player_->engine()->length();
const float percentage = (length == 0 ? 1 : float(position) / length);
library_->backend()->IncrementSkipCountAsync(song.id(), percentage);
@ -941,7 +940,7 @@ void MainWindow::FilePathChanged(const QString& path) {
void MainWindow::UpdateTrackPosition() {
// Track position in seconds
PlaylistItemPtr item(player_->GetCurrentItem());
const int position = std::floor(float(player_->GetEngine()->position()) / 1000.0 + 0.5);
const int position = std::floor(float(player_->engine()->position()) / 1000.0 + 0.5);
const int length = item->Metadata().length();
if (length <= 0) {
@ -1573,7 +1572,7 @@ void MainWindow::EnsureSettingsDialogCreated() {
settings_dialog_->SetLibraryDirectoryModel(library_->model()->directory_model());
#ifdef HAVE_GSTREAMER
if (GstEngine* engine = qobject_cast<GstEngine*>(player_->GetEngine())) {
if (GstEngine* engine = qobject_cast<GstEngine*>(player_->engine())) {
settings_dialog_->SetGstEngine(engine);
}
#endif
@ -1588,7 +1587,7 @@ void MainWindow::EnsureSettingsDialogCreated() {
connect(settings_dialog_.get(), SIGNAL(accepted()), osd_, SLOT(ReloadSettings()));
connect(settings_dialog_.get(), SIGNAL(accepted()), library_view_->view(), SLOT(ReloadSettings()));
connect(settings_dialog_.get(), SIGNAL(accepted()), song_info_view_, SLOT(ReloadSettings()));
connect(settings_dialog_.get(), SIGNAL(accepted()), player_->GetEngine(), SLOT(ReloadSettings()));
connect(settings_dialog_.get(), SIGNAL(accepted()), player_->engine(), SLOT(ReloadSettings()));
connect(settings_dialog_.get(), SIGNAL(accepted()), ui_->playlist->view(), SLOT(ReloadSettings()));
#ifdef ENABLE_WIIMOTEDEV
connect(settings_dialog_.get(), SIGNAL(accepted()), wiimotedev_shortcuts_.get(), SLOT(ReloadSettings()));
@ -1657,7 +1656,7 @@ void MainWindow::ShowVisualisations() {
connect(playlists_, SIGNAL(CurrentSongChanged(Song)), visualisation_.get(), SLOT(SongMetadataChanged(Song)));
#ifdef HAVE_GSTREAMER
if (GstEngine* engine = qobject_cast<GstEngine*>(player_->GetEngine()))
if (GstEngine* engine = qobject_cast<GstEngine*>(player_->engine()))
visualisation_->SetEngine(engine);
#endif
}