Remove support for mpris1
This commit is contained in:
parent
807e4552e1
commit
ed13d02231
@ -891,17 +891,6 @@ optional_source(LINUX SOURCES widgets/osd_x11.cpp)
|
||||
if(HAVE_DBUS)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus)
|
||||
|
||||
# MPRIS DBUS interfaces
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
dbus/org.freedesktop.MediaPlayer.player.xml
|
||||
core/mpris1.h mpris::Mpris1Player core/mpris_player MprisPlayer)
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
dbus/org.freedesktop.MediaPlayer.root.xml
|
||||
core/mpris1.h mpris::Mpris1Root core/mpris_root MprisRoot)
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
dbus/org.freedesktop.MediaPlayer.tracklist.xml
|
||||
core/mpris1.h mpris::Mpris1TrackList core/mpris_tracklist MprisTrackList)
|
||||
|
||||
# MPRIS 2.0 DBUS interfaces
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
dbus/org.mpris.MediaPlayer2.Player.xml
|
||||
@ -981,13 +970,11 @@ endif(HAVE_DBUS)
|
||||
optional_source(HAVE_DBUS
|
||||
SOURCES
|
||||
core/mpris.cpp
|
||||
core/mpris1.cpp
|
||||
core/mpris2.cpp
|
||||
networkremote/avahi.cpp
|
||||
ui/dbusscreensaver.cpp
|
||||
HEADERS
|
||||
core/mpris.h
|
||||
core/mpris1.h
|
||||
core/mpris2.h
|
||||
)
|
||||
|
||||
|
@ -18,15 +18,12 @@
|
||||
*/
|
||||
|
||||
#include "mpris.h"
|
||||
#include "mpris1.h"
|
||||
#include "mpris2.h"
|
||||
|
||||
namespace mpris {
|
||||
|
||||
Mpris::Mpris(Application* app, QObject* parent)
|
||||
: QObject(parent),
|
||||
mpris1_(new mpris::Mpris1(app, this)),
|
||||
mpris2_(new mpris::Mpris2(app, mpris1_, this)) {
|
||||
: QObject(parent), mpris2_(new mpris::Mpris2(app, this)) {
|
||||
connect(mpris2_, SIGNAL(RaiseMainWindow()), SIGNAL(RaiseMainWindow()));
|
||||
}
|
||||
|
||||
|
@ -1,377 +0,0 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2011, Paweł Bara <keirangtp@gmail.com>
|
||||
Copyright 2011-2012, David Sansome <me@davidsansome.com>
|
||||
Copyright 2013, Uwe Klotz <uwe.klotz@gmail.com>
|
||||
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||
Copyright 2014, John Maguire <john.maguire@gmail.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 "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "covers/currentartloader.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDBusConnection>
|
||||
|
||||
#include "core/mpris_player.h"
|
||||
#include "core/mpris_root.h"
|
||||
#include "core/mpris_tracklist.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "engines/enginebase.h"
|
||||
#include "playlist/playlist.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/playlistsequence.h"
|
||||
|
||||
namespace mpris {
|
||||
|
||||
const char* Mpris1::kDefaultDbusServiceName = "org.mpris.clementine";
|
||||
|
||||
Mpris1::Mpris1(Application* app, QObject* parent,
|
||||
const QString& dbus_service_name)
|
||||
: QObject(parent),
|
||||
dbus_service_name_(dbus_service_name),
|
||||
root_(nullptr),
|
||||
player_(nullptr),
|
||||
tracklist_(nullptr) {
|
||||
qDBusRegisterMetaType<DBusStatus>();
|
||||
qDBusRegisterMetaType<Version>();
|
||||
|
||||
if (dbus_service_name_.isEmpty()) {
|
||||
dbus_service_name_ = kDefaultDbusServiceName;
|
||||
}
|
||||
|
||||
if (!QDBusConnection::sessionBus().registerService(dbus_service_name_)) {
|
||||
qLog(Warning) << "Failed to register" << dbus_service_name_
|
||||
<< "on the session bus";
|
||||
return;
|
||||
}
|
||||
|
||||
root_ = new Mpris1Root(app, this);
|
||||
player_ = new Mpris1Player(app, this);
|
||||
tracklist_ = new Mpris1TrackList(app, this);
|
||||
|
||||
connect(app->current_art_loader(),
|
||||
SIGNAL(ArtLoaded(const Song&, const QString&, const QImage&)),
|
||||
player_,
|
||||
SLOT(CurrentSongChanged(const Song&, const QString&, const QImage&)));
|
||||
}
|
||||
|
||||
Mpris1::~Mpris1() {
|
||||
QDBusConnection::sessionBus().unregisterService(dbus_service_name_);
|
||||
}
|
||||
|
||||
Mpris1Root::Mpris1Root(Application* app, QObject* parent)
|
||||
: QObject(parent), app_(app) {
|
||||
new MprisRoot(this);
|
||||
QDBusConnection::sessionBus().registerObject("/", this);
|
||||
}
|
||||
|
||||
Mpris1Player::Mpris1Player(Application* app, QObject* parent)
|
||||
: QObject(parent), app_(app) {
|
||||
new MprisPlayer(this);
|
||||
QDBusConnection::sessionBus().registerObject("/Player", this);
|
||||
|
||||
connect(app_->player()->engine(), SIGNAL(StateChanged(Engine::State)),
|
||||
SLOT(EngineStateChanged(Engine::State)));
|
||||
connect(app_->playlist_manager(), SIGNAL(PlaylistManagerInitialized()),
|
||||
SLOT(PlaylistManagerInitialized()));
|
||||
}
|
||||
|
||||
// when PlaylistManager gets it ready, we connect PlaylistSequence with this
|
||||
void Mpris1Player::PlaylistManagerInitialized() {
|
||||
connect(app_->playlist_manager()->sequence(),
|
||||
SIGNAL(ShuffleModeChanged(PlaylistSequence::ShuffleMode)),
|
||||
SLOT(ShuffleModeChanged()));
|
||||
connect(app_->playlist_manager()->sequence(),
|
||||
SIGNAL(RepeatModeChanged(PlaylistSequence::RepeatMode)),
|
||||
SLOT(RepeatModeChanged()));
|
||||
}
|
||||
|
||||
Mpris1TrackList::Mpris1TrackList(Application* app, QObject* parent)
|
||||
: QObject(parent), app_(app) {
|
||||
new MprisTrackList(this);
|
||||
QDBusConnection::sessionBus().registerObject("/TrackList", this);
|
||||
|
||||
connect(app_->playlist_manager(), 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,
|
||||
const QImage&) {
|
||||
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() { app_->player()->PlayPause(); }
|
||||
|
||||
void Mpris1Player::Stop() { app_->player()->Stop(); }
|
||||
|
||||
void Mpris1Player::Prev() { app_->player()->Previous(); }
|
||||
|
||||
void Mpris1Player::Play() { app_->player()->Play(); }
|
||||
|
||||
void Mpris1Player::Next() { app_->player()->Next(); }
|
||||
|
||||
void Mpris1Player::Repeat(bool repeat) {
|
||||
app_->playlist_manager()->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(app_->player()->GetState());
|
||||
}
|
||||
|
||||
DBusStatus Mpris1Player::GetStatus(Engine::State state) const {
|
||||
DBusStatus status;
|
||||
switch (state) {
|
||||
case Engine::Playing:
|
||||
status.play = DBusStatus::Mpris_Playing;
|
||||
break;
|
||||
case Engine::Paused:
|
||||
status.play = DBusStatus::Mpris_Paused;
|
||||
break;
|
||||
case Engine::Empty:
|
||||
case Engine::Idle:
|
||||
default:
|
||||
status.play = DBusStatus::Mpris_Stopped;
|
||||
break;
|
||||
}
|
||||
|
||||
if (app_->playlist_manager()->sequence()) {
|
||||
PlaylistManagerInterface* playlists_ = app_->playlist_manager();
|
||||
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) { app_->player()->SetVolume(volume); }
|
||||
|
||||
int Mpris1Player::VolumeGet() const { return app_->player()->GetVolume(); }
|
||||
|
||||
void Mpris1Player::PositionSet(int pos_msec) {
|
||||
app_->player()->SeekTo(pos_msec / kMsecPerSec);
|
||||
}
|
||||
|
||||
int Mpris1Player::PositionGet() const {
|
||||
return app_->player()->engine()->position_nanosec() / kNsecPerMsec;
|
||||
}
|
||||
|
||||
QVariantMap Mpris1Player::GetMetadata() const { return last_metadata_; }
|
||||
|
||||
int Mpris1Player::GetCaps() const {
|
||||
return GetCaps(app_->player()->GetState());
|
||||
}
|
||||
|
||||
int Mpris1Player::GetCaps(Engine::State state) const {
|
||||
int caps = CAN_HAS_TRACKLIST;
|
||||
PlaylistItemPtr current_item = app_->player()->GetCurrentItem();
|
||||
PlaylistManagerInterface* playlists = app_->playlist_manager();
|
||||
|
||||
if (playlists->active()) {
|
||||
// play is disabled when playlist is empty or when last.fm stream is already
|
||||
// playing
|
||||
if (playlists->active() && playlists->active()->rowCount() != 0 &&
|
||||
!(state == Engine::Playing &&
|
||||
(app_->player()->GetCurrentItem()->options() &
|
||||
PlaylistItem::LastFMControls))) {
|
||||
caps |= CAN_PLAY;
|
||||
}
|
||||
|
||||
if (playlists->active()->next_row() != -1) {
|
||||
caps |= CAN_GO_NEXT;
|
||||
}
|
||||
if (playlists->active()->previous_row() != -1 ||
|
||||
app_->player()->PreviousWouldRestartTrack()) {
|
||||
caps |= CAN_GO_PREV;
|
||||
}
|
||||
}
|
||||
|
||||
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().is_stream()) {
|
||||
caps |= CAN_SEEK;
|
||||
}
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
void Mpris1Player::VolumeUp(int change) { VolumeSet(VolumeGet() + change); }
|
||||
|
||||
void Mpris1Player::VolumeDown(int change) { VolumeSet(VolumeGet() - change); }
|
||||
|
||||
void Mpris1Player::Mute() { app_->player()->Mute(); }
|
||||
|
||||
void Mpris1Player::ShowOSD() { app_->player()->ShowOSD(); }
|
||||
|
||||
int Mpris1TrackList::AddTrack(const QString& track, bool play) {
|
||||
app_->playlist_manager()->active()->InsertUrls(QList<QUrl>() << QUrl(track),
|
||||
-1, play);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Mpris1TrackList::DelTrack(int index) {
|
||||
app_->playlist_manager()->active()->removeRows(index, 1);
|
||||
}
|
||||
|
||||
int Mpris1TrackList::GetCurrentTrack() const {
|
||||
return app_->playlist_manager()->active()->current_row();
|
||||
}
|
||||
|
||||
int Mpris1TrackList::GetLength() const {
|
||||
return app_->playlist_manager()->active()->rowCount();
|
||||
}
|
||||
|
||||
QVariantMap Mpris1TrackList::GetMetadata(int pos) const {
|
||||
PlaylistItemPtr item = app_->player()->GetItemAt(pos);
|
||||
if (!item) return QVariantMap();
|
||||
|
||||
return Mpris1::GetMetadata(item->Metadata());
|
||||
}
|
||||
|
||||
void Mpris1TrackList::SetLoop(bool enable) {
|
||||
app_->playlist_manager()->active()->sequence()->SetRepeatMode(
|
||||
enable ? PlaylistSequence::Repeat_Playlist
|
||||
: PlaylistSequence::Repeat_Off);
|
||||
}
|
||||
|
||||
void Mpris1TrackList::SetRandom(bool enable) {
|
||||
app_->playlist_manager()->active()->sequence()->SetShuffleMode(
|
||||
enable ? PlaylistSequence::Shuffle_All : PlaylistSequence::Shuffle_Off);
|
||||
}
|
||||
|
||||
void Mpris1TrackList::PlayTrack(int index) {
|
||||
app_->player()->PlayAt(index, Engine::Manual, true);
|
||||
}
|
||||
|
||||
QVariantMap Mpris1::GetMetadata(const Song& song) {
|
||||
QVariantMap ret;
|
||||
|
||||
AddMetadata("location", song.url().toString(), &ret);
|
||||
AddMetadata("title", song.PrettyTitle(), &ret);
|
||||
AddMetadata("artist", song.artist(), &ret);
|
||||
AddMetadata("album", song.album(), &ret);
|
||||
AddMetadata("time", song.length_nanosec() / kNsecPerSec, &ret);
|
||||
AddMetadata("mtime", song.length_nanosec() / kNsecPerMsec, &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("performer", song.performer(), &ret);
|
||||
AddMetadata("grouping", song.grouping(), &ret);
|
||||
AddMetadata("lyrics", song.lyrics(), &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;
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2011-2012, David Sansome <me@davidsansome.com>
|
||||
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
|
||||
Copyright 2014, John Maguire <john.maguire@gmail.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 CORE_MPRIS1_H_
|
||||
#define CORE_MPRIS1_H_
|
||||
|
||||
#include "core/player.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDBusArgument>
|
||||
#include <QObject>
|
||||
|
||||
class Application;
|
||||
class Playlist;
|
||||
|
||||
struct DBusStatus { // From Amarok.
|
||||
DBusStatus()
|
||||
: play(Mpris_Stopped), random(0), repeat(0), repeat_playlist(0) {}
|
||||
|
||||
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 Mpris1Root;
|
||||
class Mpris1Player;
|
||||
class Mpris1TrackList;
|
||||
|
||||
class Mpris1 : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Mpris1(Application* app, QObject* parent = nullptr,
|
||||
const QString& dbus_service_name = QString());
|
||||
~Mpris1();
|
||||
|
||||
static QVariantMap GetMetadata(const Song& song);
|
||||
|
||||
Mpris1Root* root() const { return root_; }
|
||||
Mpris1Player* player() const { return player_; }
|
||||
Mpris1TrackList* tracklist() const { return tracklist_; }
|
||||
|
||||
private:
|
||||
static const char* kDefaultDbusServiceName;
|
||||
|
||||
QString dbus_service_name_;
|
||||
|
||||
Mpris1Root* root_;
|
||||
Mpris1Player* player_;
|
||||
Mpris1TrackList* tracklist_;
|
||||
};
|
||||
|
||||
class Mpris1Root : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Mpris1Root(Application* app, QObject* parent = nullptr);
|
||||
|
||||
QString Identity();
|
||||
void Quit();
|
||||
Version MprisVersion();
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
};
|
||||
|
||||
class Mpris1Player : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Mpris1Player(Application* app, QObject* parent = nullptr);
|
||||
|
||||
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_msec);
|
||||
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,
|
||||
const QImage&);
|
||||
|
||||
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:
|
||||
Application* app_;
|
||||
|
||||
QVariantMap last_metadata_;
|
||||
};
|
||||
|
||||
class Mpris1TrackList : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Mpris1TrackList(Application* app, QObject* parent = nullptr);
|
||||
|
||||
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:
|
||||
Application* app_;
|
||||
};
|
||||
|
||||
} // namespace mpris
|
||||
|
||||
#endif // CORE_MPRIS1_H_
|
@ -25,11 +25,14 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
#include "config.h"
|
||||
#include "mpris_common.h"
|
||||
#include "mpris1.h"
|
||||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/mpris_common.h"
|
||||
#include "core/mpris2_player.h"
|
||||
#include "core/mpris2_playlists.h"
|
||||
#include "core/mpris2_root.h"
|
||||
@ -43,10 +46,6 @@
|
||||
#include "playlist/playlistsequence.h"
|
||||
#include "ui/mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
QDBusArgument& operator<<(QDBusArgument& arg, const MprisPlaylist& playlist) {
|
||||
arg.beginStructure();
|
||||
arg << playlist.id << playlist.name << playlist.icon;
|
||||
@ -84,8 +83,7 @@ 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(Application* app, Mpris1* mpris1, QObject* parent)
|
||||
: QObject(parent), app_(app), mpris1_(mpris1) {
|
||||
Mpris2::Mpris2(Application* app, QObject* parent) : QObject(parent), app_(app) {
|
||||
new Mpris2Root(this);
|
||||
new Mpris2TrackList(this);
|
||||
new Mpris2Player(this);
|
||||
@ -305,35 +303,25 @@ double Mpris2::Rate() const { return 1.0; }
|
||||
|
||||
void Mpris2::SetRate(double rate) {
|
||||
if (rate == 0) {
|
||||
if (mpris1_->player()) {
|
||||
mpris1_->player()->Pause();
|
||||
}
|
||||
app_->player()->Pause();
|
||||
}
|
||||
}
|
||||
|
||||
bool Mpris2::Shuffle() const {
|
||||
if (mpris1_->player()) {
|
||||
return mpris1_->player()->GetStatus().random;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return app_->playlist_manager()->sequence()->shuffle_mode() !=
|
||||
PlaylistSequence::Shuffle_Off;
|
||||
}
|
||||
|
||||
void Mpris2::SetShuffle(bool value) {
|
||||
if (mpris1_->tracklist()) {
|
||||
mpris1_->tracklist()->SetRandom(value);
|
||||
}
|
||||
void Mpris2::SetShuffle(bool enable) {
|
||||
app_->playlist_manager()->active()->sequence()->SetShuffleMode(
|
||||
enable ? PlaylistSequence::Shuffle_All : PlaylistSequence::Shuffle_Off);
|
||||
}
|
||||
|
||||
QVariantMap Mpris2::Metadata() const { return last_metadata_; }
|
||||
|
||||
QString Mpris2::current_track_id() const {
|
||||
if (!mpris1_->tracklist()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString("/org/mpris/MediaPlayer2/Track/%1")
|
||||
.arg(QString::number(mpris1_->tracklist()->GetCurrentTrack()));
|
||||
.arg(QString::number(app_->playlist_manager()->active()->current_row()));
|
||||
}
|
||||
|
||||
// We send Metadata change notification as soon as the process of
|
||||
@ -366,13 +354,7 @@ void Mpris2::ArtLoaded(const Song& song, const QString& art_uri) {
|
||||
EmitNotification("Metadata", last_metadata_);
|
||||
}
|
||||
|
||||
double Mpris2::Volume() const {
|
||||
if (mpris1_->player()) {
|
||||
return static_cast<double>(mpris1_->player()->VolumeGet()) / 100;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
double Mpris2::Volume() const { return app_->player()->GetVolume() / 100.0; }
|
||||
|
||||
void Mpris2::SetVolume(double value) { app_->player()->SetVolume(value * 100); }
|
||||
|
||||
@ -385,41 +367,39 @@ double Mpris2::MaximumRate() const { return 1.0; }
|
||||
double Mpris2::MinimumRate() const { return 1.0; }
|
||||
|
||||
bool Mpris2::CanGoNext() const {
|
||||
if (mpris1_->player()) {
|
||||
return mpris1_->player()->GetCaps() & CAN_GO_NEXT;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return app_->playlist_manager()->active() &&
|
||||
app_->playlist_manager()->active()->next_row() != -1;
|
||||
}
|
||||
|
||||
bool Mpris2::CanGoPrevious() const {
|
||||
if (mpris1_->player()) {
|
||||
return mpris1_->player()->GetCaps() & CAN_GO_PREV;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return app_->playlist_manager()->active() &&
|
||||
(app_->playlist_manager()->active()->previous_row() != -1 ||
|
||||
app_->player()->PreviousWouldRestartTrack());
|
||||
}
|
||||
|
||||
bool Mpris2::CanPlay() const { return mpris1_->player()->GetCaps() & CAN_PLAY; }
|
||||
bool Mpris2::CanPlay() const {
|
||||
return app_->playlist_manager()->active() &&
|
||||
app_->playlist_manager()->active()->rowCount() != 0 &&
|
||||
!(app_->player()->GetState() == Engine::Playing &&
|
||||
(app_->player()->GetCurrentItem()->options() &
|
||||
PlaylistItem::LastFMControls));
|
||||
}
|
||||
|
||||
// This one's a bit different than MPRIS 1 - we want this to be true even when
|
||||
// the song is already paused or stopped.
|
||||
bool Mpris2::CanPause() const {
|
||||
if (mpris1_->player()) {
|
||||
return mpris1_->player()->GetCaps() & CAN_PAUSE ||
|
||||
PlaybackStatus() == "Paused" || PlaybackStatus() == "Stopped";
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return (app_->player()->GetCurrentItem() &&
|
||||
app_->player()->GetState() == Engine::Playing &&
|
||||
!(app_->player()->GetCurrentItem()->options() &
|
||||
PlaylistItem::PauseDisabled)) ||
|
||||
PlaybackStatus() == "Paused" || PlaybackStatus() == "Stopped";
|
||||
}
|
||||
|
||||
bool Mpris2::CanSeek() const {
|
||||
return mpris1_->player() ? mpris1_->player()->GetCaps() & CAN_SEEK : true;
|
||||
}
|
||||
bool Mpris2::CanSeek() const { return CanSeek(app_->player()->GetState()); }
|
||||
|
||||
bool Mpris2::CanSeek(Engine::State state) const {
|
||||
return mpris1_->player() ? mpris1_->player()->GetCaps(state) & CAN_SEEK
|
||||
: true;
|
||||
return app_->player()->GetCurrentItem() && state != Engine::Empty &&
|
||||
!app_->player()->GetCurrentItem()->Metadata().is_stream();
|
||||
}
|
||||
|
||||
bool Mpris2::CanControl() const { return true; }
|
||||
@ -476,9 +456,8 @@ void Mpris2::SetPosition(const QDBusObjectPath& trackId, qlonglong offset) {
|
||||
}
|
||||
|
||||
void Mpris2::OpenUri(const QString& uri) {
|
||||
if (mpris1_->tracklist()) {
|
||||
mpris1_->tracklist()->AddTrack(uri, true);
|
||||
}
|
||||
app_->playlist_manager()->active()->InsertUrls(QList<QUrl>() << QUrl(uri), -1,
|
||||
true);
|
||||
}
|
||||
|
||||
TrackIds Mpris2::Tracks() const {
|
||||
|
@ -22,12 +22,12 @@
|
||||
#ifndef CORE_MPRIS2_H_
|
||||
#define CORE_MPRIS2_H_
|
||||
|
||||
#include "playlist/playlistitem.h"
|
||||
|
||||
#include <QMetaObject>
|
||||
#include <QObject>
|
||||
#include <QtDBus>
|
||||
|
||||
#include "playlist/playlistitem.h"
|
||||
|
||||
class Application;
|
||||
class MainWindow;
|
||||
class Playlist;
|
||||
@ -61,12 +61,12 @@ const QDBusArgument& operator>>(const QDBusArgument& arg,
|
||||
|
||||
namespace mpris {
|
||||
|
||||
class Mpris1;
|
||||
|
||||
class Mpris2 : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Mpris2(Application* app, QObject* parent = nullptr);
|
||||
|
||||
// org.mpris.MediaPlayer2 MPRIS 2.0 Root interface
|
||||
Q_PROPERTY(bool CanQuit READ CanQuit)
|
||||
Q_PROPERTY(bool CanRaise READ CanRaise)
|
||||
@ -106,8 +106,6 @@ class Mpris2 : public QObject {
|
||||
Q_PROPERTY(QStringList Orderings READ Orderings)
|
||||
Q_PROPERTY(MaybePlaylist ActivePlaylist READ ActivePlaylist)
|
||||
|
||||
Mpris2(Application* app, Mpris1* mpris1, QObject* parent = nullptr);
|
||||
|
||||
// Root Properties
|
||||
bool CanQuit() const;
|
||||
bool CanRaise() const;
|
||||
@ -179,7 +177,7 @@ class Mpris2 : public QObject {
|
||||
QList<MprisPlaylist> GetPlaylists(quint32 index, quint32 max_count,
|
||||
const QString& order, bool reverse_order);
|
||||
|
||||
signals:
|
||||
signals:
|
||||
// Player
|
||||
void Seeked(qlonglong position);
|
||||
|
||||
@ -229,7 +227,6 @@ class Mpris2 : public QObject {
|
||||
QVariantMap last_metadata_;
|
||||
|
||||
Application* app_;
|
||||
Mpris1* mpris1_;
|
||||
};
|
||||
|
||||
} // namespace mpris
|
||||
|
@ -1,91 +0,0 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
|
||||
|
||||
<node>
|
||||
<interface name="org.freedesktop.MediaPlayer">
|
||||
|
||||
<method name="Pause">
|
||||
</method>
|
||||
|
||||
<method name="Stop">
|
||||
</method>
|
||||
|
||||
<method name="Play">
|
||||
</method>
|
||||
|
||||
<method name="Prev">
|
||||
</method>
|
||||
|
||||
<method name="Next">
|
||||
</method>
|
||||
|
||||
<method name="Repeat">
|
||||
<arg type="b" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="GetStatus">
|
||||
<arg type="(iiii)" direction="out">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="DBusStatus"/>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="VolumeSet">
|
||||
<arg type="i" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="VolumeGet">
|
||||
<arg type="i" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="PositionSet">
|
||||
<arg type="i" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="PositionGet">
|
||||
<arg type="i" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="GetMetadata">
|
||||
<arg type="a{sv}" direction="out">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="GetCaps">
|
||||
<arg type="i" direction="out" />
|
||||
</method>
|
||||
|
||||
<signal name="TrackChange">
|
||||
<arg type="a{sv}">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
|
||||
</arg>
|
||||
</signal>
|
||||
|
||||
<signal name="StatusChange">
|
||||
<arg type="(iiii)">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="DBusStatus"/>
|
||||
</arg>
|
||||
</signal>
|
||||
|
||||
<signal name="CapsChange">
|
||||
<arg type="i" />
|
||||
</signal>
|
||||
|
||||
<!-- NB: Amarok extensions to the mpris spec -->
|
||||
<method name="VolumeUp">
|
||||
<arg type="i" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="VolumeDown">
|
||||
<arg type="i" direction="in"/>
|
||||
</method>
|
||||
|
||||
<method name="Mute">
|
||||
</method>
|
||||
|
||||
<method name="ShowOSD">
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
</node>
|
@ -1,21 +0,0 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
|
||||
|
||||
<node>
|
||||
<interface name="org.freedesktop.MediaPlayer">
|
||||
<method name="Identity">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="Quit">
|
||||
</method>
|
||||
|
||||
<method name="MprisVersion">
|
||||
<arg type="(qq)" direction="out">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="Version"/>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
</node>
|
@ -1,49 +0,0 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
|
||||
<node>
|
||||
<interface name="org.freedesktop.MediaPlayer">
|
||||
|
||||
<method name="GetMetadata">
|
||||
<arg type="i" direction="in" />
|
||||
<arg type="a{sv}" direction="out">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="GetCurrentTrack">
|
||||
<arg type="i" direction="out" />
|
||||
</method>
|
||||
|
||||
<method name="GetLength">
|
||||
<arg type="i" direction="out" />
|
||||
</method>
|
||||
|
||||
<method name="AddTrack">
|
||||
<arg type="s" direction="in" />
|
||||
<arg type="b" direction="in" />
|
||||
<arg type="i" direction="out" />
|
||||
</method>
|
||||
|
||||
<method name="DelTrack">
|
||||
<arg direction="in" type="i" />
|
||||
</method>
|
||||
|
||||
<method name="SetLoop">
|
||||
<arg direction="in" type="b" />
|
||||
</method>
|
||||
|
||||
<method name="SetRandom">
|
||||
<arg direction="in" type="b" />
|
||||
</method>
|
||||
|
||||
<method name="PlayTrack">
|
||||
<arg direction="in" type="i" />
|
||||
</method>
|
||||
|
||||
<signal name="TrackListChange">
|
||||
<arg type="i" />
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
Loading…
x
Reference in New Issue
Block a user