1 /*
2  * Strawberry Music Player
3  * This file was part of Clementine.
4  * Copyright 2010, David Sansome <me@davidsansome.com>
5  * Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
6  *
7  * Strawberry is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * Strawberry is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Strawberry.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef MPRIS2_H
23 #define MPRIS2_H
24 
25 #include "config.h"
26 
27 #include <QtGlobal>
28 #include <QObject>
29 #include <QList>
30 #include <QMap>
31 #include <QSet>
32 #include <QMetaType>
33 #include <QVariant>
34 #include <QString>
35 #include <QStringList>
36 #include <QtDBus>
37 #include <QDBusArgument>
38 #include <qdbusextratypes.h>
39 #include <QJsonObject>
40 
41 #include "engine/engine_fwd.h"
42 #include "covermanager/albumcoverloaderresult.h"
43 
44 class Application;
45 class Song;
46 class Playlist;
47 
48 typedef QList<QVariantMap> TrackMetadata;
49 typedef QList<QDBusObjectPath> Track_Ids;
50 Q_DECLARE_METATYPE(TrackMetadata)
51 
52 struct MprisPlaylist {
53   QDBusObjectPath id;
54   QString name;
55   QString icon;  // Uri
56 };
57 typedef QList<MprisPlaylist> MprisPlaylistList;
58 Q_DECLARE_METATYPE(MprisPlaylist)
59 Q_DECLARE_METATYPE(MprisPlaylistList)
60 
61 struct MaybePlaylist {
62   bool valid;
63   MprisPlaylist playlist;
64 };
65 Q_DECLARE_METATYPE(MaybePlaylist)
66 
67 QDBusArgument &operator<<(QDBusArgument &arg, const MprisPlaylist &playlist);
68 const QDBusArgument &operator>>(const QDBusArgument &arg, MprisPlaylist &playlist);
69 
70 QDBusArgument &operator<<(QDBusArgument &arg, const MaybePlaylist &playlist);
71 const QDBusArgument &operator>>(const QDBusArgument &arg, MaybePlaylist &playlist);
72 
73 namespace mpris {
74 
75 class Mpris2 : public QObject {
76   Q_OBJECT
77 
78  public:
79   explicit Mpris2(Application *app, QObject *parent = nullptr);
80 
81   // org.mpris.MediaPlayer2 MPRIS 2.0 Root interface
82   Q_PROPERTY(bool CanQuit READ CanQuit)
83   Q_PROPERTY(bool CanRaise READ CanRaise)
84   Q_PROPERTY(bool HasTrackList READ HasTrackList)
85   Q_PROPERTY(QString Identity READ Identity)
86   Q_PROPERTY(QString DesktopEntry READ DesktopEntry)
87   Q_PROPERTY(QStringList SupportedUriSchemes READ SupportedUriSchemes)
88   Q_PROPERTY(QStringList SupportedMimeTypes READ SupportedMimeTypes)
89 
90   // org.mpris.MediaPlayer2 MPRIS 2.2 Root interface
91   Q_PROPERTY(bool CanSetFullscreen READ CanSetFullscreen)
92   Q_PROPERTY(bool Fullscreen READ Fullscreen WRITE SetFullscreen)
93 
94   // org.mpris.MediaPlayer2.Player MPRIS 2.0 Player interface
95   Q_PROPERTY(QString PlaybackStatus READ PlaybackStatus)
96   Q_PROPERTY(QString LoopStatus READ LoopStatus WRITE SetLoopStatus)
97   Q_PROPERTY(double Rate READ Rate WRITE SetRate)
98   Q_PROPERTY(bool Shuffle READ Shuffle WRITE SetShuffle)
99   Q_PROPERTY(QVariantMap Metadata READ Metadata)
100   Q_PROPERTY(double Volume READ Volume WRITE SetVolume)
101   Q_PROPERTY(qint64 Position READ Position)
102   Q_PROPERTY(double MinimumRate READ MinimumRate)
103   Q_PROPERTY(double MaximumRate READ MaximumRate)
104   Q_PROPERTY(bool CanGoNext READ CanGoNext)
105   Q_PROPERTY(bool CanGoPrevious READ CanGoPrevious)
106   Q_PROPERTY(bool CanPlay READ CanPlay)
107   Q_PROPERTY(bool CanPause READ CanPause)
108   Q_PROPERTY(bool CanSeek READ CanSeek)
109   Q_PROPERTY(bool CanControl READ CanControl)
110 
111   // org.mpris.MediaPlayer2.TrackList MPRIS 2.0 Player interface
112   Q_PROPERTY(Track_Ids Tracks READ Tracks)
113   Q_PROPERTY(bool CanEditTracks READ CanEditTracks)
114 
115   // org.mpris.MediaPlayer2.Playlists MPRIS 2.1 Playlists interface
116   Q_PROPERTY(quint32 PlaylistCount READ PlaylistCount)
117   Q_PROPERTY(QStringList Orderings READ Orderings)
118   Q_PROPERTY(MaybePlaylist ActivePlaylist READ ActivePlaylist)
119 
120   // Root Properties
121   bool CanQuit() const;
122   bool CanRaise() const;
123   bool HasTrackList() const;
124   QString Identity() const;
125   QString DesktopEntry() const;
126   QStringList SupportedUriSchemes() const;
127   QStringList SupportedMimeTypes() const;
128 
129   // Root Properties added in MPRIS 2.2
CanSetFullscreen()130   bool CanSetFullscreen() const { return false; }
Fullscreen()131   bool Fullscreen() const { return false; }
SetFullscreen(bool)132   void SetFullscreen(bool) {}
133 
134   // Methods
135   void Raise();
136   void Quit();
137 
138   // Player Properties
139   QString PlaybackStatus() const;
140   QString LoopStatus() const;
141   void SetLoopStatus(const QString &value);
142   double Rate() const;
143   void SetRate(double rate);
144   bool Shuffle() const;
145   void SetShuffle(bool enable);
146   QVariantMap Metadata() const;
147   double Volume() const;
148   void SetVolume(double value);
149   qint64 Position() const;
150   double MaximumRate() const;
151   double MinimumRate() const;
152   bool CanGoNext() const;
153   bool CanGoPrevious() const;
154   bool CanPlay() const;
155   bool CanPause() const;
156   bool CanSeek() const;
157   bool CanControl() const;
158 
159   // Methods
160   void Next();
161   void Previous();
162   void Pause();
163   void PlayPause();
164   void Stop();
165   void Play();
166   void Seek(qint64 offset);
167   void SetPosition(const QDBusObjectPath &trackId, qint64 offset);
168   void OpenUri(const QString &uri);
169 
170   // TrackList Properties
171   Track_Ids Tracks() const;
172   bool CanEditTracks() const;
173 
174   // Methods
175   TrackMetadata GetTracksMetadata(const Track_Ids &tracks) const;
176   void AddTrack(const QString &uri, const QDBusObjectPath &afterTrack, bool setAsCurrent);
177   void RemoveTrack(const QDBusObjectPath &trackId);
178   void GoTo(const QDBusObjectPath &trackId);
179 
180   // Playlist Properties
181   quint32 PlaylistCount() const;
182   QStringList Orderings() const;
183   MaybePlaylist ActivePlaylist() const;
184 
185   // Methods
186   void ActivatePlaylist(const QDBusObjectPath &playlist_id);
187   MprisPlaylistList GetPlaylists(quint32 index, quint32 max_count, const QString &order, bool reverse_order);
188 
189  signals:
190   // Player
191   void Seeked(qint64 position);
192 
193   // TrackList
194   void TrackListReplaced(Track_Ids Tracks, QDBusObjectPath CurrentTrack);
195   void TrackAdded(TrackMetadata Metadata, QDBusObjectPath AfterTrack);
196   void TrackRemoved(QDBusObjectPath trackId);
197   void TrackMetadataChanged(QDBusObjectPath trackId, TrackMetadata metadata);
198 
199   void RaiseMainWindow();
200 
201   // Playlist
202   void PlaylistChanged(MprisPlaylist playlist);
203 
204  private slots:
205   void AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &result = AlbumCoverLoaderResult());
206   void EngineStateChanged(Engine::State newState);
207   void VolumeChanged();
208 
209   void PlaylistManagerInitialized();
210   void CurrentSongChanged(const Song &song);
211   void ShuffleModeChanged();
212   void RepeatModeChanged();
213   void PlaylistChangedSlot(Playlist *playlist);
214   void PlaylistCollectionChanged(Playlist *playlist);
215 
216  private:
217   void EmitNotification(const QString &name);
218   void EmitNotification(const QString &name, const QVariant &val);
219   void EmitNotification(const QString &name, const QVariant &val, const QString &mprisEntity);
220 
221   QString PlaybackStatus(Engine::State state) const;
222 
223   QString current_track_id() const;
224 
225   bool CanSeek(Engine::State state) const;
226 
227   QString DesktopEntryAbsolutePath() const;
228 
229  private:
230   static const char *kMprisObjectPath;
231   static const char *kServiceName;
232   static const char *kFreedesktopPath;
233 
234   Application *app_;
235 
236   QString app_name_;
237   QStringList data_dirs_;
238   QStringList desktop_files_;
239   QString desktop_file_;
240   QVariantMap last_metadata_;
241 
242 };
243 
244 }  // namespace mpris
245 
246 
247 #endif  // MPRIS2_H
248