parent
4de0b93305
commit
d674d9ecf7
|
@ -866,6 +866,11 @@ if(HAVE_DBUS)
|
|||
dbus/org.mpris.MediaPlayer2.TrackList.xml
|
||||
core/mpris2.h mpris::Mpris2 core/mpris2_tracklist Mpris2TrackList)
|
||||
|
||||
# MPRIS 2.1 DBUS interfaces
|
||||
qt4_add_dbus_adaptor(SOURCES
|
||||
dbus/org.mpris.MediaPlayer2.Playlists.xml
|
||||
core/mpris2.h mpris::Mpris2 core/mpris2_playlists Mpris2Playlists)
|
||||
|
||||
# org.freedesktop.Notifications DBUS interface
|
||||
qt4_add_dbus_interface(SOURCES
|
||||
dbus/org.freedesktop.Notifications.xml
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#cmakedefine HAVE_IMOBILEDEVICE
|
||||
#cmakedefine HAVE_LIBARCHIVE
|
||||
#cmakedefine HAVE_LIBGPOD
|
||||
#cmakedefine HAVE_LIBINDICATE
|
||||
#cmakedefine HAVE_LIBLASTFM
|
||||
#cmakedefine HAVE_LIBLASTFM1
|
||||
#cmakedefine HAVE_LIBMTP
|
||||
|
|
|
@ -73,5 +73,8 @@ void RegisterMetaTypes() {
|
|||
qDBusRegisterMetaType<TrackMetadata>();
|
||||
qDBusRegisterMetaType<TrackIds>();
|
||||
qDBusRegisterMetaType<QList<QByteArray> >();
|
||||
qDBusRegisterMetaType<MprisPlaylist>();
|
||||
qDBusRegisterMetaType<MaybePlaylist>();
|
||||
qDBusRegisterMetaType<MprisPlaylistList>();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ Mpris::Mpris(Application* app, QObject* parent)
|
|||
mpris2_(new mpris::Mpris2(app, mpris1_, this))
|
||||
{
|
||||
connect(mpris2_, SIGNAL(RaiseMainWindow()), SIGNAL(RaiseMainWindow()));
|
||||
mpris2_->InitLibIndicate();
|
||||
}
|
||||
|
||||
} // namespace mpris
|
||||
|
|
|
@ -15,13 +15,17 @@
|
|||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mpris2.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "config.h"
|
||||
#include "mpris_common.h"
|
||||
#include "mpris1.h"
|
||||
#include "mpris2.h"
|
||||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/mpris2_player.h"
|
||||
#include "core/mpris2_playlists.h"
|
||||
#include "core/mpris2_root.h"
|
||||
#include "core/mpris2_tracklist.h"
|
||||
#include "core/player.h"
|
||||
|
@ -37,9 +41,36 @@
|
|||
#include <QDBusConnection>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
#ifdef HAVE_LIBINDICATE
|
||||
# include <qindicateserver.h>
|
||||
#endif
|
||||
QDBusArgument& operator<< (QDBusArgument& arg, const MprisPlaylist& playlist) {
|
||||
arg.beginStructure();
|
||||
arg << playlist.id << playlist.name << playlist.icon;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
const QDBusArgument& operator>> (
|
||||
const QDBusArgument& arg, MprisPlaylist& playlist) {
|
||||
arg.beginStructure();
|
||||
arg >> playlist.id >> playlist.name >> playlist.icon;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
QDBusArgument& operator<< (QDBusArgument& arg, const MaybePlaylist& playlist) {
|
||||
arg.beginStructure();
|
||||
arg << playlist.valid;
|
||||
arg << playlist.playlist;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
const QDBusArgument& operator>> (
|
||||
const QDBusArgument& arg, MaybePlaylist& playlist) {
|
||||
arg.beginStructure();
|
||||
arg >> playlist.valid >> playlist.playlist;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
namespace mpris {
|
||||
|
||||
|
@ -55,6 +86,7 @@ Mpris2::Mpris2(Application* app, Mpris1* mpris1, QObject* parent)
|
|||
new Mpris2Root(this);
|
||||
new Mpris2TrackList(this);
|
||||
new Mpris2Player(this);
|
||||
new Mpris2Playlists(this);
|
||||
|
||||
if (!QDBusConnection::sessionBus().registerService(kServiceName)) {
|
||||
qLog(Warning) << "Failed to register" << QString(kServiceName) << "on the session bus";
|
||||
|
@ -71,15 +103,7 @@ Mpris2::Mpris2(Application* app, Mpris1* mpris1, QObject* parent)
|
|||
|
||||
connect(app_->playlist_manager(), SIGNAL(PlaylistManagerInitialized()), SLOT(PlaylistManagerInitialized()));
|
||||
connect(app_->playlist_manager(), 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
|
||||
connect(app_->playlist_manager(), SIGNAL(PlaylistChanged(Playlist*)), SLOT(PlaylistChanged()));
|
||||
}
|
||||
|
||||
// when PlaylistManager gets it ready, we connect PlaylistSequence with this
|
||||
|
@ -474,4 +498,75 @@ void Mpris2::GoTo(const QDBusObjectPath &trackId) {
|
|||
//TODO
|
||||
}
|
||||
|
||||
quint32 Mpris2::PlaylistCount() const {
|
||||
return app_->playlist_manager()->GetAllPlaylists().size();
|
||||
}
|
||||
|
||||
QStringList Mpris2::Orderings() const {
|
||||
return QStringList() << "User";
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
QDBusObjectPath MakePlaylistPath(int id) {
|
||||
return QDBusObjectPath(QString(
|
||||
"/org/mpris/MediaPlayer2/Playlists/%1").arg(id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MaybePlaylist Mpris2::ActivePlaylist() const {
|
||||
MaybePlaylist maybe_playlist;
|
||||
Playlist* current_playlist = app_->playlist_manager()->current();
|
||||
maybe_playlist.valid = current_playlist;
|
||||
if (!current_playlist) {
|
||||
return maybe_playlist;
|
||||
}
|
||||
|
||||
maybe_playlist.playlist.id = MakePlaylistPath(current_playlist->id());
|
||||
maybe_playlist.playlist.name =
|
||||
app_->playlist_manager()->GetPlaylistName(current_playlist->id());
|
||||
return maybe_playlist;
|
||||
}
|
||||
|
||||
void Mpris2::ActivatePlaylist(const QDBusObjectPath& playlist_id) {
|
||||
QStringList split_path = playlist_id.path().split('/');
|
||||
qLog(Debug) << Q_FUNC_INFO << playlist_id.path() << split_path;
|
||||
if (split_path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
bool ok = false;
|
||||
int p = split_path.last().toInt(&ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
app_->playlist_manager()->SetActivePlaylist(p);
|
||||
app_->player()->Next();
|
||||
}
|
||||
|
||||
// TODO: Support sort orders.
|
||||
MprisPlaylistList Mpris2::GetPlaylists(
|
||||
quint32 index, quint32 max_count, const QString& order, bool reverse_order) {
|
||||
MprisPlaylistList ret;
|
||||
foreach (Playlist* p, app_->playlist_manager()->GetAllPlaylists()) {
|
||||
MprisPlaylist mpris_playlist;
|
||||
mpris_playlist.id = MakePlaylistPath(p->id());
|
||||
mpris_playlist.name = app_->playlist_manager()->GetPlaylistName(p->id());
|
||||
ret << mpris_playlist;
|
||||
}
|
||||
|
||||
if (reverse_order) {
|
||||
std::reverse(ret.begin(), ret.end());
|
||||
}
|
||||
|
||||
return ret.mid(index, max_count);
|
||||
}
|
||||
|
||||
void Mpris2::PlaylistChanged(Playlist* playlist) {
|
||||
MprisPlaylist mpris_playlist;
|
||||
mpris_playlist.id = MakePlaylistPath(playlist->id());
|
||||
mpris_playlist.name = app_->playlist_manager()->GetPlaylistName(playlist->id());
|
||||
emit PlaylistChanged(mpris_playlist);
|
||||
}
|
||||
|
||||
} // namespace mpris
|
||||
|
|
|
@ -28,11 +28,36 @@
|
|||
|
||||
class Application;
|
||||
class MainWindow;
|
||||
class Playlist;
|
||||
|
||||
typedef QList<QVariantMap> TrackMetadata;
|
||||
typedef QList<QDBusObjectPath> TrackIds;
|
||||
Q_DECLARE_METATYPE(TrackMetadata)
|
||||
|
||||
struct MprisPlaylist {
|
||||
QDBusObjectPath id;
|
||||
QString name;
|
||||
QString icon; // Uri
|
||||
};
|
||||
typedef QList<MprisPlaylist> MprisPlaylistList;
|
||||
Q_DECLARE_METATYPE(MprisPlaylist);
|
||||
Q_DECLARE_METATYPE(MprisPlaylistList);
|
||||
|
||||
struct MaybePlaylist {
|
||||
bool valid;
|
||||
MprisPlaylist playlist;
|
||||
};
|
||||
Q_DECLARE_METATYPE(MaybePlaylist);
|
||||
|
||||
QDBusArgument& operator<< (QDBusArgument& arg, const MprisPlaylist& playlist);
|
||||
const QDBusArgument& operator>> (
|
||||
const QDBusArgument& arg, MprisPlaylist& playlist);
|
||||
|
||||
QDBusArgument& operator<< (QDBusArgument& arg, const MaybePlaylist& playlist);
|
||||
const QDBusArgument& operator>> (
|
||||
const QDBusArgument& arg, MaybePlaylist& playlist);
|
||||
|
||||
|
||||
namespace mpris {
|
||||
|
||||
class Mpris1;
|
||||
|
@ -40,6 +65,7 @@ class Mpris1;
|
|||
class Mpris2 : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//org.mpris.MediaPlayer2 MPRIS 2.0 Root interface
|
||||
Q_PROPERTY( bool CanQuit READ CanQuit )
|
||||
Q_PROPERTY( bool CanRaise READ CanRaise )
|
||||
|
@ -74,10 +100,12 @@ class Mpris2 : public QObject {
|
|||
Q_PROPERTY( TrackIds Tracks READ Tracks )
|
||||
Q_PROPERTY( bool CanEditTracks READ CanEditTracks )
|
||||
|
||||
public:
|
||||
Mpris2(Application* app, Mpris1* mpris1, QObject* parent = 0);
|
||||
//org.mpris.MediaPlayer2.Playlists MPRIS 2.1 Playlists interface
|
||||
Q_PROPERTY( quint32 PlaylistCount READ PlaylistCount )
|
||||
Q_PROPERTY( QStringList Orderings READ Orderings )
|
||||
Q_PROPERTY( MaybePlaylist ActivePlaylist READ ActivePlaylist )
|
||||
|
||||
void InitLibIndicate();
|
||||
Mpris2(Application* app, Mpris1* mpris1, QObject* parent = 0);
|
||||
|
||||
// Root Properties
|
||||
bool CanQuit() const;
|
||||
|
@ -139,6 +167,16 @@ public:
|
|||
void RemoveTrack(const QDBusObjectPath& trackId);
|
||||
void GoTo(const QDBusObjectPath& trackId);
|
||||
|
||||
// Playlist Properties
|
||||
quint32 PlaylistCount() const;
|
||||
QStringList Orderings() const;
|
||||
MaybePlaylist ActivePlaylist() const;
|
||||
|
||||
// Methods
|
||||
void ActivatePlaylist(const QDBusObjectPath& playlist_id);
|
||||
QList<MprisPlaylist> GetPlaylists(
|
||||
quint32 index, quint32 max_count, const QString& order, bool reverse_order);
|
||||
|
||||
signals:
|
||||
// Player
|
||||
void Seeked(qlonglong position);
|
||||
|
@ -151,6 +189,9 @@ signals:
|
|||
|
||||
void RaiseMainWindow();
|
||||
|
||||
// Playlist
|
||||
void PlaylistChanged(const MprisPlaylist& playlist);
|
||||
|
||||
private slots:
|
||||
void ArtLoaded(const Song& song, const QString& art_uri);
|
||||
void EngineStateChanged(Engine::State newState);
|
||||
|
@ -160,6 +201,7 @@ private slots:
|
|||
void CurrentSongChanged(const Song& song);
|
||||
void ShuffleModeChanged();
|
||||
void RepeatModeChanged();
|
||||
void PlaylistChanged(Playlist* playlist);
|
||||
|
||||
private:
|
||||
void EmitNotification(const QString& name);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<!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.mpris.MediaPlayer2.Playlists'>
|
||||
<property name='PlaylistCount' type='u' access='read' />
|
||||
<property name='Orderings' type='as' access='read' />
|
||||
<property name='ActivePlaylist' type='(b(oss))' access='read'>
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName" value="MaybePlaylist"/>
|
||||
</property>
|
||||
<method name='ActivatePlaylist'>
|
||||
<arg direction='in' name='PlaylistId' type='o' />
|
||||
</method>
|
||||
<method name='GetPlaylists'>
|
||||
<arg direction='in' name='Index' type='u' />
|
||||
<arg direction='in' name='MaxCount' type='u' />
|
||||
<arg direction='in' name='Order' type='s' />
|
||||
<arg direction='in' name='ReverseOrder' type='b' />
|
||||
<arg direction='out' name='Playlists' type='a(oss)' />
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MprisPlaylistList"/>
|
||||
</method>
|
||||
<signal name='PlaylistChanged'>
|
||||
<arg name='Playlist' type='(oss)' />
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MprisPlaylist" />
|
||||
</signal>
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName" value="MaybePlaylist" />
|
||||
</interface>
|
||||
</node>
|
Loading…
Reference in New Issue