From 987dd8c57a71c092d09a64444ad41fd7b587dff7 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sat, 4 Dec 2010 22:27:58 +0000 Subject: [PATCH] Refactor and fix most of the MPRIS code. Fixes issue #374 --- src/CMakeLists.txt | 18 +- src/core/mpris.cpp | 502 +++++++++++++++++++++----------------- src/core/mpris.h | 133 +++++----- src/core/mpris2.cpp | 196 +++++++-------- src/core/mpris2.h | 33 ++- src/core/mpris_common.cpp | 69 ++++++ src/core/mpris_common.h | 82 +++++++ src/core/player.cpp | 74 +----- src/core/player.h | 18 +- src/ui/mainwindow.cpp | 27 +- 10 files changed, 654 insertions(+), 498 deletions(-) create mode 100644 src/core/mpris_common.cpp create mode 100644 src/core/mpris_common.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5124f667f..40f1fd0d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/core/mpris.cpp b/src/core/mpris.cpp index ffba92c40..3f817566a 100644 --- a/src/core/mpris.cpp +++ b/src/core/mpris.cpp @@ -16,6 +16,7 @@ */ #include "mpris.h" +#include "mpris_common.h" #include #include @@ -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(); + qDBusRegisterMetaType(); + + 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 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; } diff --git a/src/core/mpris.h b/src/core/mpris.h index ebf822ca6..7ce70372e 100644 --- a/src/core/mpris.h +++ b/src/core/mpris.h @@ -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& 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 - - - diff --git a/src/core/mpris2.cpp b/src/core/mpris2.cpp index 16f52b968..71561ed7c 100644 --- a/src/core/mpris2.cpp +++ b/src/core/mpris2.cpp @@ -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 #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(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 diff --git a/src/core/mpris2.h b/src/core/mpris2.h index 6905094f2..6cb7d5c91 100644 --- a/src/core/mpris2.h +++ b/src/core/mpris2.h @@ -18,7 +18,6 @@ #ifndef MPRIS2_H #define MPRIS2_H -#include "core/backgroundthread.h" #include "playlist/playlistitem.h" #include @@ -27,17 +26,18 @@ #include -class AlbumCoverLoader; class MainWindow; class Player; -class QTemporaryFile; - typedef QList TrackMetadata; typedef QList 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 temp_art_; - BackgroundThread* cover_loader_; - quint64 art_request_id_; - PlaylistItemPtr art_request_item_; - QVariantMap last_metadata_; MainWindow* ui_; Player* player_; }; +} // namespace mpris + #endif diff --git a/src/core/mpris_common.cpp b/src/core/mpris_common.cpp new file mode 100644 index 000000000..65c6a1c36 --- /dev/null +++ b/src/core/mpris_common.cpp @@ -0,0 +1,69 @@ +/* This file is part of Clementine. + Copyright 2010, David Sansome + + 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 . +*/ + +#include "albumcoverloader.h" +#include "mpris_common.h" + +#include +#include + +namespace mpris { + +ArtLoader::ArtLoader(QObject* parent) + : QObject(parent), + cover_loader_(new BackgroundThreadImplementation(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 diff --git a/src/core/mpris_common.h b/src/core/mpris_common.h new file mode 100644 index 000000000..a8671879b --- /dev/null +++ b/src/core/mpris_common.h @@ -0,0 +1,82 @@ +/* This file is part of Clementine. + Copyright 2010, David Sansome + + 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 . +*/ + +#ifndef MPRIS_COMMON_H +#define MPRIS_COMMON_H + +#include "backgroundthread.h" +#include "song.h" + +#include +#include +#include +#include + +#include + +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 temp_art_; + BackgroundThread* 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 diff --git a/src/core/player.cpp b/src/core/player.cpp index 645462f4c..b0cf2f051 100644 --- a/src/core/player.cpp +++ b/src/core/player.cpp @@ -37,6 +37,7 @@ #endif #ifdef Q_WS_X11 +# include "mpris_common.h" # include "mpris.h" # include "mpris2.h" # include @@ -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(); - qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); + + // 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 diff --git a/src/core/player.h b/src/core/player.h index f321bec7f..287c5de03 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -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_; diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index a2db6a168..9e9e8efc9 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -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(player_->GetEngine()) == NULL) { + if (qobject_cast(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)), - player_->GetEngine(), SLOT(SetEqualizerParameters(int,QList))); + player_->engine(), SLOT(SetEqualizerParameters(int,QList))); 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(player_->GetEngine())) { + if (GstEngine* engine = qobject_cast(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(player_->GetEngine())) + if (GstEngine* engine = qobject_cast(player_->engine())) visualisation_->SetEngine(engine); #endif }