mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-17 20:09:50 +01:00
Move MPRIS setup to a background thread
This commit is contained in:
parent
7a089faa29
commit
b3c211e26a
@ -565,13 +565,13 @@ if(HAVE_DBUS)
|
||||
# MPRIS DBUS interfaces
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
dbus/org.freedesktop.MediaPlayer.player.xml
|
||||
core/mpris.h mpris::Mpris1Player core/mpris_player MprisPlayer)
|
||||
core/mpris1.h mpris::Mpris1Player core/mpris_player MprisPlayer)
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
dbus/org.freedesktop.MediaPlayer.root.xml
|
||||
core/mpris.h mpris::Mpris1Root core/mpris_root MprisRoot)
|
||||
core/mpris1.h mpris::Mpris1Root core/mpris_root MprisRoot)
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
dbus/org.freedesktop.MediaPlayer.tracklist.xml
|
||||
core/mpris.h mpris::Mpris1TrackList core/mpris_tracklist MprisTrackList)
|
||||
core/mpris1.h mpris::Mpris1TrackList core/mpris_tracklist MprisTrackList)
|
||||
|
||||
# MPRIS 2.0 DBUS interfaces
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
@ -600,8 +600,8 @@ if(HAVE_DBUS)
|
||||
endif(HAVE_DEVICEKIT)
|
||||
|
||||
# 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.cpp core/mpris1.cpp core/mpris2.cpp)
|
||||
list(APPEND HEADERS core/mpris.h core/mpris1.h core/mpris2.h)
|
||||
|
||||
# Wiimotedev interface classes
|
||||
if(ENABLE_WIIMOTEDEV)
|
||||
@ -735,6 +735,8 @@ list(APPEND OTHER_SOURCES
|
||||
core/modelfuturewatcher.h
|
||||
core/mpris.cpp
|
||||
core/mpris.h
|
||||
core/mpris1.cpp
|
||||
core/mpris1.h
|
||||
core/mpris2.cpp
|
||||
core/mpris2.h
|
||||
devices/afcdevice.cpp
|
||||
|
@ -16,342 +16,45 @@
|
||||
*/
|
||||
|
||||
#include "mpris.h"
|
||||
#include "mpris_common.h"
|
||||
#include "mpris1.h"
|
||||
#include "mpris2.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDBusConnection>
|
||||
|
||||
#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"
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
namespace mpris {
|
||||
|
||||
Mpris1::Mpris1(Player* player, ArtLoader* art_loader, QObject* parent)
|
||||
: QObject(parent)
|
||||
Mpris::Mpris(Player* player, ArtLoader* art_loader, QObject* parent)
|
||||
: QObject(parent),
|
||||
player_(player),
|
||||
art_loader_(art_loader),
|
||||
mpris1_(NULL),
|
||||
mpris2_(NULL)
|
||||
{
|
||||
qDBusRegisterMetaType<DBusStatus>();
|
||||
qDBusRegisterMetaType<Version>();
|
||||
QFuture<void> future = QtConcurrent::run(this, &Mpris::Init);
|
||||
|
||||
QDBusConnection::sessionBus().registerService("org.mpris.clementine");
|
||||
root_ = new Mpris1Root(player, this);
|
||||
player_ = new Mpris1Player(player, this);
|
||||
tracklist_ = new Mpris1TrackList(player, this);
|
||||
QFutureWatcher<void>* watcher = new QFutureWatcher<void>(this);
|
||||
watcher->setFuture(future);
|
||||
|
||||
connect(art_loader, SIGNAL(ArtLoaded(Song,QString)),
|
||||
player_, SLOT(CurrentSongChanged(Song,QString)));
|
||||
connect(watcher, SIGNAL(finished()), SLOT(Initialised()));
|
||||
}
|
||||
|
||||
Mpris1Root::Mpris1Root(Player* player, QObject* parent)
|
||||
: QObject(parent), player_(player) {
|
||||
new MprisRoot(this);
|
||||
QDBusConnection::sessionBus().registerObject("/", this);
|
||||
void Mpris::Init() {
|
||||
mpris1_ = new mpris::Mpris1(player_, art_loader_);
|
||||
mpris2_ = new mpris::Mpris2(player_, art_loader_, mpris1_);
|
||||
|
||||
mpris1_->moveToThread(thread());
|
||||
mpris2_->moveToThread(thread());
|
||||
|
||||
mpris1_->setParent(this);
|
||||
mpris2_->setParent(this);
|
||||
|
||||
connect(mpris2_, SIGNAL(RaiseMainWindow()), SIGNAL(RaiseMainWindow()));
|
||||
}
|
||||
|
||||
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(Engine::State)));
|
||||
connect(player_->playlists(), SIGNAL(PlaylistManagerInitialized()), SLOT(PlaylistManagerInitialized()));
|
||||
}
|
||||
|
||||
// when PlaylistManager gets it ready, we connect PlaylistSequence with this
|
||||
void Mpris1Player::PlaylistManagerInitialized() {
|
||||
connect(player_->playlists()->sequence(), SIGNAL(ShuffleModeChanged(PlaylistSequence::ShuffleMode)),
|
||||
SLOT(ShuffleModeChanged()));
|
||||
connect(player_->playlists()->sequence(), SIGNAL(RepeatModeChanged(PlaylistSequence::RepeatMode)),
|
||||
SLOT(RepeatModeChanged()));
|
||||
}
|
||||
|
||||
Mpris1TrackList::Mpris1TrackList(Player* player, QObject* parent)
|
||||
: QObject(parent), player_(player) {
|
||||
new MprisTrackList(this);
|
||||
QDBusConnection::sessionBus().registerObject("/TrackList", this);
|
||||
|
||||
connect(player->playlists(), SIGNAL(PlaylistChanged(Playlist*)), SLOT(PlaylistChanged(Playlist*)));
|
||||
}
|
||||
|
||||
void Mpris1TrackList::PlaylistChanged(Playlist* playlist) {
|
||||
emit TrackListChange(playlist->rowCount());
|
||||
}
|
||||
|
||||
// we use the state from event and don't try to obtain it from Player
|
||||
// later because only the event's version is really the current one
|
||||
void Mpris1Player::EngineStateChanged(Engine::State state) {
|
||||
emit StatusChange(GetStatus(state));
|
||||
emit CapsChange(GetCaps(state));
|
||||
}
|
||||
|
||||
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_->Previous();
|
||||
}
|
||||
|
||||
void Mpris1Player::Play() {
|
||||
player_->Play();
|
||||
}
|
||||
|
||||
void Mpris1Player::Next() {
|
||||
player_->Next();
|
||||
}
|
||||
|
||||
void Mpris1Player::Repeat(bool repeat) {
|
||||
player_->playlists()->sequence()->SetRepeatMode(
|
||||
repeat ? PlaylistSequence::Repeat_Track : PlaylistSequence::Repeat_Off);
|
||||
}
|
||||
|
||||
void Mpris1Player::ShuffleModeChanged() {
|
||||
emit StatusChange(GetStatus());
|
||||
}
|
||||
|
||||
void Mpris1Player::RepeatModeChanged() {
|
||||
emit StatusChange(GetStatus());
|
||||
}
|
||||
|
||||
DBusStatus Mpris1Player::GetStatus() const {
|
||||
return GetStatus(player_->GetState());
|
||||
}
|
||||
|
||||
DBusStatus Mpris1Player::GetStatus(Engine::State state) const {
|
||||
DBusStatus status;
|
||||
switch (state) {
|
||||
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_->GetVolume();
|
||||
}
|
||||
|
||||
void Mpris1Player::PositionSet(int pos) {
|
||||
player_->Seek(pos/1000);
|
||||
}
|
||||
|
||||
int Mpris1Player::PositionGet() const {
|
||||
return player_->engine()->position();
|
||||
}
|
||||
|
||||
QVariantMap Mpris1Player::GetMetadata() const {
|
||||
return last_metadata_;
|
||||
}
|
||||
|
||||
int Mpris1Player::GetCaps() const {
|
||||
return GetCaps(player_->GetState());
|
||||
}
|
||||
|
||||
int Mpris1Player::GetCaps(Engine::State state) const {
|
||||
int caps = CAN_HAS_TRACKLIST;
|
||||
PlaylistItemPtr current_item = player_->GetCurrentItem();
|
||||
PlaylistManager* playlists = player_->playlists();
|
||||
|
||||
// play is disabled when playlist is empty or when last.fm stream is already playing
|
||||
if (playlists->active()->rowCount() != 0
|
||||
&& !(state == Engine::Playing && (player_->GetCurrentItem()->options() & PlaylistItem::LastFMControls))) {
|
||||
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_row() != -1 ||
|
||||
playlists->active()->current_item_options() & PlaylistItem::ContainsMultipleTracks) {
|
||||
caps |= CAN_GO_NEXT;
|
||||
}
|
||||
if (playlists->active()->previous_row() != -1) {
|
||||
caps |= CAN_GO_PREV;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
void Mpris1Player::VolumeUp(int change) {
|
||||
VolumeSet(VolumeGet() + change);
|
||||
}
|
||||
|
||||
void Mpris1Player::VolumeDown(int change) {
|
||||
VolumeSet(VolumeGet() - change);
|
||||
}
|
||||
|
||||
void Mpris1Player::Mute() {
|
||||
player_->Mute();
|
||||
}
|
||||
|
||||
void Mpris1Player::ShowOSD() {
|
||||
player_->ShowOSD();
|
||||
}
|
||||
|
||||
int Mpris1TrackList::AddTrack(const QString& track, bool play) {
|
||||
player_->playlists()->active()->InsertUrls(
|
||||
QList<QUrl>() << QUrl(track), play);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Mpris1TrackList::DelTrack(int index) {
|
||||
player_->playlists()->active()->removeRows(index, 1);
|
||||
}
|
||||
|
||||
int Mpris1TrackList::GetCurrentTrack() const {
|
||||
return player_->playlists()->active()->current_row();
|
||||
}
|
||||
|
||||
int Mpris1TrackList::GetLength() const {
|
||||
return player_->playlists()->active()->rowCount();
|
||||
}
|
||||
|
||||
QVariantMap Mpris1TrackList::GetMetadata(int pos) const {
|
||||
PlaylistItemPtr item = player_->GetItemAt(pos);
|
||||
if (!item)
|
||||
return QVariantMap();
|
||||
|
||||
return Mpris1::GetMetadata(item->Metadata());
|
||||
}
|
||||
|
||||
void Mpris1TrackList::SetLoop(bool enable) {
|
||||
player_->playlists()->active()->sequence()->SetRepeatMode(
|
||||
enable ? PlaylistSequence::Repeat_Playlist : PlaylistSequence::Repeat_Off);
|
||||
}
|
||||
|
||||
void Mpris1TrackList::SetRandom(bool enable) {
|
||||
player_->playlists()->active()->sequence()->SetShuffleMode(
|
||||
enable ? PlaylistSequence::Shuffle_All : PlaylistSequence::Shuffle_Off);
|
||||
}
|
||||
|
||||
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);
|
||||
if (song.rating() != -1.0) {
|
||||
AddMetadata("rating", song.rating() * 5, &ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
void Mpris::Initialised() {
|
||||
mpris2_->InitLibIndicate();
|
||||
}
|
||||
|
||||
} // namespace mpris
|
||||
|
||||
|
||||
QDBusArgument& operator<< (QDBusArgument& arg, const Version& version) {
|
||||
arg.beginStructure();
|
||||
arg << version.major << version.minor;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
const QDBusArgument& operator>> (const QDBusArgument& arg, Version& version) {
|
||||
arg.beginStructure();
|
||||
arg >> version.major >> version.minor;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
161
src/core/mpris.h
161
src/core/mpris.h
@ -18,176 +18,37 @@
|
||||
#ifndef MPRIS_H
|
||||
#define MPRIS_H
|
||||
|
||||
#include "core/player.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDBusArgument>
|
||||
#include <QObject>
|
||||
|
||||
class Player;
|
||||
class Playlist;
|
||||
|
||||
struct DBusStatus { // From Amarok.
|
||||
int play; // Playing = 0, Paused = 1, Stopped = 2
|
||||
int random; // Linearly = 0, Randomly = 1
|
||||
int repeat; // Go_To_Next = 0, Repeat_Current = 1
|
||||
int repeat_playlist; // Stop_When_Finished = 0, Never_Give_Up_Playing = 1, Never_Let_You_Down = 42
|
||||
|
||||
enum MprisPlayState {
|
||||
Mpris_Playing = 0,
|
||||
Mpris_Paused = 1,
|
||||
Mpris_Stopped = 2,
|
||||
};
|
||||
};
|
||||
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);
|
||||
|
||||
QDBusArgument& operator <<(QDBusArgument& arg, const Version& version);
|
||||
const QDBusArgument& operator >>(const QDBusArgument& arg, Version& version);
|
||||
|
||||
|
||||
namespace mpris {
|
||||
|
||||
enum DBusCaps {
|
||||
NONE = 0,
|
||||
CAN_GO_NEXT = 1 << 0,
|
||||
CAN_GO_PREV = 1 << 1,
|
||||
CAN_PAUSE = 1 << 2,
|
||||
CAN_PLAY = 1 << 3,
|
||||
CAN_SEEK = 1 << 4,
|
||||
CAN_PROVIDE_METADATA = 1 << 5,
|
||||
CAN_HAS_TRACKLIST = 1 << 6,
|
||||
};
|
||||
|
||||
|
||||
class ArtLoader;
|
||||
class Mpris1Root;
|
||||
class Mpris1Player;
|
||||
class Mpris1TrackList;
|
||||
class Mpris1;
|
||||
class Mpris2;
|
||||
|
||||
|
||||
class Mpris1 : public QObject {
|
||||
class Mpris : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Mpris1(Player* player, ArtLoader* art_loader, QObject* parent = 0);
|
||||
|
||||
static QVariantMap GetMetadata(const Song& song);
|
||||
|
||||
Mpris1Root* root() const { return root_; }
|
||||
Mpris1Player* player() const { return player_; }
|
||||
Mpris1TrackList* tracklist() const { return tracklist_; }
|
||||
|
||||
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();
|
||||
|
||||
private:
|
||||
Player* player_;
|
||||
};
|
||||
|
||||
|
||||
class Mpris1Player : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Mpris1Player(Player* player, QObject* parent);
|
||||
|
||||
void Pause();
|
||||
void Stop();
|
||||
void Prev();
|
||||
void Play();
|
||||
void Next();
|
||||
void Repeat(bool);
|
||||
|
||||
// those methods will use engine's state obtained with player->GetState() method
|
||||
DBusStatus GetStatus() const;
|
||||
int GetCaps() const;
|
||||
// those methods will use engine's state provided as an argument
|
||||
DBusStatus GetStatus(Engine::State state) const;
|
||||
int GetCaps(Engine::State state) const;
|
||||
|
||||
void VolumeSet(int volume);
|
||||
int VolumeGet() const;
|
||||
void PositionSet(int pos);
|
||||
int PositionGet() const;
|
||||
QVariantMap GetMetadata() const;
|
||||
|
||||
// Amarok extensions
|
||||
void VolumeUp(int vol);
|
||||
void VolumeDown(int vol);
|
||||
void Mute();
|
||||
void ShowOSD();
|
||||
|
||||
public slots:
|
||||
void CurrentSongChanged(const Song& song, const QString& art_uri);
|
||||
Mpris(Player* player, ArtLoader* art_loader, QObject* parent = 0);
|
||||
|
||||
signals:
|
||||
void CapsChange(int);
|
||||
void TrackChange(const QVariantMap&);
|
||||
void StatusChange(DBusStatus);
|
||||
void RaiseMainWindow();
|
||||
|
||||
private slots:
|
||||
void PlaylistManagerInitialized();
|
||||
void Initialised();
|
||||
|
||||
void EngineStateChanged(Engine::State state);
|
||||
void ShuffleModeChanged();
|
||||
void RepeatModeChanged();
|
||||
private:
|
||||
void Init();
|
||||
|
||||
private:
|
||||
Player* player_;
|
||||
ArtLoader* art_loader_;
|
||||
|
||||
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;
|
||||
int GetLength() const;
|
||||
QVariantMap GetMetadata(int) const;
|
||||
void SetLoop(bool enable);
|
||||
void SetRandom(bool enable);
|
||||
|
||||
// Amarok extension
|
||||
void PlayTrack(int index);
|
||||
|
||||
signals:
|
||||
void TrackListChange(int i);
|
||||
|
||||
private slots:
|
||||
void PlaylistChanged(Playlist* playlist);
|
||||
|
||||
private:
|
||||
Player* player_;
|
||||
Mpris1* mpris1_;
|
||||
Mpris2* mpris2_;
|
||||
};
|
||||
|
||||
} // namespace mpris
|
||||
|
358
src/core/mpris1.cpp
Normal file
358
src/core/mpris1.cpp
Normal file
@ -0,0 +1,358 @@
|
||||
/* 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 "mpris1.h"
|
||||
#include "mpris_common.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDBusConnection>
|
||||
|
||||
#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(Engine::State)));
|
||||
connect(player_->playlists(), SIGNAL(PlaylistManagerInitialized()), SLOT(PlaylistManagerInitialized()));
|
||||
}
|
||||
|
||||
// when PlaylistManager gets it ready, we connect PlaylistSequence with this
|
||||
void Mpris1Player::PlaylistManagerInitialized() {
|
||||
connect(player_->playlists()->sequence(), SIGNAL(ShuffleModeChanged(PlaylistSequence::ShuffleMode)),
|
||||
SLOT(ShuffleModeChanged()));
|
||||
connect(player_->playlists()->sequence(), SIGNAL(RepeatModeChanged(PlaylistSequence::RepeatMode)),
|
||||
SLOT(RepeatModeChanged()));
|
||||
}
|
||||
|
||||
Mpris1TrackList::Mpris1TrackList(Player* player, QObject* parent)
|
||||
: QObject(parent), player_(player) {
|
||||
new MprisTrackList(this);
|
||||
QDBusConnection::sessionBus().registerObject("/TrackList", this);
|
||||
|
||||
connect(player->playlists(), SIGNAL(PlaylistChanged(Playlist*)), SLOT(PlaylistChanged(Playlist*)));
|
||||
}
|
||||
|
||||
void Mpris1TrackList::PlaylistChanged(Playlist* playlist) {
|
||||
emit TrackListChange(playlist->rowCount());
|
||||
}
|
||||
|
||||
// we use the state from event and don't try to obtain it from Player
|
||||
// later because only the event's version is really the current one
|
||||
void Mpris1Player::EngineStateChanged(Engine::State state) {
|
||||
emit StatusChange(GetStatus(state));
|
||||
emit CapsChange(GetCaps(state));
|
||||
}
|
||||
|
||||
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_->Previous();
|
||||
}
|
||||
|
||||
void Mpris1Player::Play() {
|
||||
player_->Play();
|
||||
}
|
||||
|
||||
void Mpris1Player::Next() {
|
||||
player_->Next();
|
||||
}
|
||||
|
||||
void Mpris1Player::Repeat(bool repeat) {
|
||||
player_->playlists()->sequence()->SetRepeatMode(
|
||||
repeat ? PlaylistSequence::Repeat_Track : PlaylistSequence::Repeat_Off);
|
||||
}
|
||||
|
||||
void Mpris1Player::ShuffleModeChanged() {
|
||||
emit StatusChange(GetStatus());
|
||||
}
|
||||
|
||||
void Mpris1Player::RepeatModeChanged() {
|
||||
emit StatusChange(GetStatus());
|
||||
}
|
||||
|
||||
DBusStatus Mpris1Player::GetStatus() const {
|
||||
return GetStatus(player_->GetState());
|
||||
}
|
||||
|
||||
DBusStatus Mpris1Player::GetStatus(Engine::State state) const {
|
||||
DBusStatus status;
|
||||
switch (state) {
|
||||
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_->GetVolume();
|
||||
}
|
||||
|
||||
void Mpris1Player::PositionSet(int pos) {
|
||||
player_->Seek(pos/1000);
|
||||
}
|
||||
|
||||
int Mpris1Player::PositionGet() const {
|
||||
return player_->engine()->position();
|
||||
}
|
||||
|
||||
QVariantMap Mpris1Player::GetMetadata() const {
|
||||
return last_metadata_;
|
||||
}
|
||||
|
||||
int Mpris1Player::GetCaps() const {
|
||||
return GetCaps(player_->GetState());
|
||||
}
|
||||
|
||||
int Mpris1Player::GetCaps(Engine::State state) const {
|
||||
int caps = CAN_HAS_TRACKLIST;
|
||||
PlaylistItemPtr current_item = player_->GetCurrentItem();
|
||||
PlaylistManager* playlists = player_->playlists();
|
||||
|
||||
// play is disabled when playlist is empty or when last.fm stream is already playing
|
||||
if (playlists->active()->rowCount() != 0
|
||||
&& !(state == Engine::Playing && (player_->GetCurrentItem()->options() & PlaylistItem::LastFMControls))) {
|
||||
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_row() != -1 ||
|
||||
playlists->active()->current_item_options() & PlaylistItem::ContainsMultipleTracks) {
|
||||
caps |= CAN_GO_NEXT;
|
||||
}
|
||||
if (playlists->active()->previous_row() != -1) {
|
||||
caps |= CAN_GO_PREV;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
void Mpris1Player::VolumeUp(int change) {
|
||||
VolumeSet(VolumeGet() + change);
|
||||
}
|
||||
|
||||
void Mpris1Player::VolumeDown(int change) {
|
||||
VolumeSet(VolumeGet() - change);
|
||||
}
|
||||
|
||||
void Mpris1Player::Mute() {
|
||||
player_->Mute();
|
||||
}
|
||||
|
||||
void Mpris1Player::ShowOSD() {
|
||||
player_->ShowOSD();
|
||||
}
|
||||
|
||||
int Mpris1TrackList::AddTrack(const QString& track, bool play) {
|
||||
player_->playlists()->active()->InsertUrls(
|
||||
QList<QUrl>() << QUrl(track), play);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Mpris1TrackList::DelTrack(int index) {
|
||||
player_->playlists()->active()->removeRows(index, 1);
|
||||
}
|
||||
|
||||
int Mpris1TrackList::GetCurrentTrack() const {
|
||||
return player_->playlists()->active()->current_row();
|
||||
}
|
||||
|
||||
int Mpris1TrackList::GetLength() const {
|
||||
return player_->playlists()->active()->rowCount();
|
||||
}
|
||||
|
||||
QVariantMap Mpris1TrackList::GetMetadata(int pos) const {
|
||||
PlaylistItemPtr item = player_->GetItemAt(pos);
|
||||
if (!item)
|
||||
return QVariantMap();
|
||||
|
||||
return Mpris1::GetMetadata(item->Metadata());
|
||||
}
|
||||
|
||||
void Mpris1TrackList::SetLoop(bool enable) {
|
||||
player_->playlists()->active()->sequence()->SetRepeatMode(
|
||||
enable ? PlaylistSequence::Repeat_Playlist : PlaylistSequence::Repeat_Off);
|
||||
}
|
||||
|
||||
void Mpris1TrackList::SetRandom(bool enable) {
|
||||
player_->playlists()->active()->sequence()->SetShuffleMode(
|
||||
enable ? PlaylistSequence::Shuffle_All : PlaylistSequence::Shuffle_Off);
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
const QDBusArgument& operator>> (const QDBusArgument& arg, Version& version) {
|
||||
arg.beginStructure();
|
||||
arg >> version.major >> version.minor;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
195
src/core/mpris1.h
Normal file
195
src/core/mpris1.h
Normal file
@ -0,0 +1,195 @@
|
||||
/* 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 MPRIS1_H
|
||||
#define MPRIS1_H
|
||||
|
||||
#include "core/player.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDBusArgument>
|
||||
#include <QObject>
|
||||
|
||||
class Player;
|
||||
class Playlist;
|
||||
|
||||
struct DBusStatus { // From Amarok.
|
||||
int play; // Playing = 0, Paused = 1, Stopped = 2
|
||||
int random; // Linearly = 0, Randomly = 1
|
||||
int repeat; // Go_To_Next = 0, Repeat_Current = 1
|
||||
int repeat_playlist; // Stop_When_Finished = 0, Never_Give_Up_Playing = 1, Never_Let_You_Down = 42
|
||||
|
||||
enum MprisPlayState {
|
||||
Mpris_Playing = 0,
|
||||
Mpris_Paused = 1,
|
||||
Mpris_Stopped = 2,
|
||||
};
|
||||
};
|
||||
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);
|
||||
|
||||
QDBusArgument& operator <<(QDBusArgument& arg, const Version& version);
|
||||
const QDBusArgument& operator >>(const QDBusArgument& arg, Version& version);
|
||||
|
||||
|
||||
namespace mpris {
|
||||
|
||||
enum DBusCaps {
|
||||
NONE = 0,
|
||||
CAN_GO_NEXT = 1 << 0,
|
||||
CAN_GO_PREV = 1 << 1,
|
||||
CAN_PAUSE = 1 << 2,
|
||||
CAN_PLAY = 1 << 3,
|
||||
CAN_SEEK = 1 << 4,
|
||||
CAN_PROVIDE_METADATA = 1 << 5,
|
||||
CAN_HAS_TRACKLIST = 1 << 6,
|
||||
};
|
||||
|
||||
|
||||
class ArtLoader;
|
||||
class Mpris1Root;
|
||||
class Mpris1Player;
|
||||
class Mpris1TrackList;
|
||||
|
||||
|
||||
class Mpris1 : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Mpris1(Player* player, ArtLoader* art_loader, QObject* parent = 0);
|
||||
|
||||
static QVariantMap GetMetadata(const Song& song);
|
||||
|
||||
Mpris1Root* root() const { return root_; }
|
||||
Mpris1Player* player() const { return player_; }
|
||||
Mpris1TrackList* tracklist() const { return tracklist_; }
|
||||
|
||||
private:
|
||||
Mpris1Root* root_;
|
||||
Mpris1Player* player_;
|
||||
Mpris1TrackList* tracklist_;
|
||||
};
|
||||
|
||||
|
||||
class Mpris1Root : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Mpris1Root(Player* player, QObject* parent = 0);
|
||||
|
||||
QString Identity();
|
||||
void Quit();
|
||||
Version MprisVersion();
|
||||
|
||||
private:
|
||||
Player* player_;
|
||||
};
|
||||
|
||||
|
||||
class Mpris1Player : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Mpris1Player(Player* player, QObject* parent = 0);
|
||||
|
||||
void Pause();
|
||||
void Stop();
|
||||
void Prev();
|
||||
void Play();
|
||||
void Next();
|
||||
void Repeat(bool);
|
||||
|
||||
// those methods will use engine's state obtained with player->GetState() method
|
||||
DBusStatus GetStatus() const;
|
||||
int GetCaps() const;
|
||||
// those methods will use engine's state provided as an argument
|
||||
DBusStatus GetStatus(Engine::State state) const;
|
||||
int GetCaps(Engine::State state) const;
|
||||
|
||||
void VolumeSet(int volume);
|
||||
int VolumeGet() const;
|
||||
void PositionSet(int pos);
|
||||
int PositionGet() const;
|
||||
QVariantMap GetMetadata() const;
|
||||
|
||||
// Amarok extensions
|
||||
void VolumeUp(int vol);
|
||||
void VolumeDown(int vol);
|
||||
void Mute();
|
||||
void ShowOSD();
|
||||
|
||||
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 PlaylistManagerInitialized();
|
||||
|
||||
void EngineStateChanged(Engine::State state);
|
||||
void ShuffleModeChanged();
|
||||
void RepeatModeChanged();
|
||||
|
||||
private:
|
||||
Player* player_;
|
||||
|
||||
QVariantMap last_metadata_;
|
||||
};
|
||||
|
||||
|
||||
class Mpris1TrackList : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Mpris1TrackList(Player* player, QObject* parent = 0);
|
||||
|
||||
int AddTrack(const QString&, bool);
|
||||
void DelTrack(int index);
|
||||
int GetCurrentTrack() const;
|
||||
int GetLength() const;
|
||||
QVariantMap GetMetadata(int) const;
|
||||
void SetLoop(bool enable);
|
||||
void SetRandom(bool enable);
|
||||
|
||||
// Amarok extension
|
||||
void PlayTrack(int index);
|
||||
|
||||
signals:
|
||||
void TrackListChange(int i);
|
||||
|
||||
private slots:
|
||||
void PlaylistChanged(Playlist* playlist);
|
||||
|
||||
private:
|
||||
Player* player_;
|
||||
};
|
||||
|
||||
} // namespace mpris
|
||||
|
||||
#endif // MPRIS1_H
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "mpris_common.h"
|
||||
#include "mpris.h"
|
||||
#include "mpris1.h"
|
||||
#include "mpris2.h"
|
||||
#include "core/mpris2_player.h"
|
||||
#include "core/mpris2_root.h"
|
||||
@ -31,6 +31,7 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
#ifdef HAVE_LIBINDICATE
|
||||
# include <qindicateserver.h>
|
||||
@ -55,21 +56,23 @@ Mpris2::Mpris2(Player* player, ArtLoader* art_loader,
|
||||
QDBusConnection::sessionBus().registerService(kServiceName);
|
||||
QDBusConnection::sessionBus().registerObject(kMprisObjectPath, this);
|
||||
|
||||
#ifdef HAVE_LIBINDICATE
|
||||
QIndicate::Server* indicate_server = QIndicate::Server::defaultInstance();
|
||||
indicate_server->setType("music.clementine");
|
||||
indicate_server->setDesktopFile(DesktopEntryAbsolutePath());
|
||||
indicate_server->show();
|
||||
#endif
|
||||
|
||||
connect(art_loader, SIGNAL(ArtLoaded(Song,QString)), SLOT(ArtLoaded(Song,QString)));
|
||||
|
||||
connect(player->engine(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State)));
|
||||
connect(player, SIGNAL(VolumeChanged(int)), SLOT(VolumeChanged()));
|
||||
connect(player, SIGNAL(Seeked(qlonglong)), SIGNAL(Seeked(qlonglong)));
|
||||
|
||||
connect(player_->playlists(), SIGNAL(PlaylistManagerInitialized()), SLOT(PlaylistManagerInitialized()));
|
||||
connect(player_->playlists(), SIGNAL(CurrentSongChanged(Song)), SLOT(CurrentSongChanged(Song)));
|
||||
connect(player->playlists(), SIGNAL(PlaylistManagerInitialized()), SLOT(PlaylistManagerInitialized()));
|
||||
connect(player->playlists(), SIGNAL(CurrentSongChanged(Song)), SLOT(CurrentSongChanged(Song)));
|
||||
}
|
||||
|
||||
void Mpris2::InitLibIndicate() {
|
||||
#ifdef HAVE_LIBINDICATE
|
||||
QIndicate::Server* indicate_server = QIndicate::Server::defaultInstance();
|
||||
indicate_server->setType("music.clementine");
|
||||
indicate_server->setDesktopFile(DesktopEntryAbsolutePath());
|
||||
indicate_server->show();
|
||||
#endif
|
||||
}
|
||||
|
||||
// when PlaylistManager gets it ready, we connect PlaylistSequence with this
|
||||
|
@ -73,6 +73,9 @@ class Mpris2 : public QObject {
|
||||
|
||||
public:
|
||||
Mpris2(Player* player, ArtLoader* art_loader, Mpris1* mpris1, QObject* parent = 0);
|
||||
|
||||
void InitLibIndicate();
|
||||
|
||||
// Root Properties
|
||||
bool CanQuit() const;
|
||||
bool CanRaise() const;
|
||||
|
@ -312,8 +312,7 @@ int main(int argc, char *argv[]) {
|
||||
qDBusRegisterMetaType<TrackIds>();
|
||||
|
||||
mpris::ArtLoader art_loader;
|
||||
mpris::Mpris1 mpris1(&player, &art_loader);
|
||||
mpris::Mpris2 mpris2(&player, &art_loader, &mpris1);
|
||||
mpris::Mpris mpris(&player, &art_loader);
|
||||
|
||||
QObject::connect(&playlists, SIGNAL(CurrentSongChanged(Song)), &art_loader, SLOT(LoadArt(Song)));
|
||||
QObject::connect(&art_loader, SIGNAL(ThumbnailLoaded(Song, QString)),
|
||||
@ -341,7 +340,7 @@ int main(int argc, char *argv[]) {
|
||||
tray_icon.get(),
|
||||
&osd);
|
||||
#ifdef HAVE_DBUS
|
||||
QObject::connect(&mpris2, SIGNAL(RaiseMainWindow()), &w, SLOT(Raise()));
|
||||
QObject::connect(&mpris, SIGNAL(RaiseMainWindow()), &w, SLOT(Raise()));
|
||||
#endif
|
||||
QObject::connect(&a, SIGNAL(messageReceived(QByteArray)), &w, SLOT(CommandlineOptionsReceived(QByteArray)));
|
||||
w.CommandlineOptionsReceived(options);
|
||||
|
Loading…
Reference in New Issue
Block a user