1 /*
2  * Cantata
3  *
4  * Copyright (c) 2011-2020 Craig Drummond <craig.p.drummond@gmail.com>
5  *
6  * ----
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; see the file COPYING.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #ifndef MPRIS_H
25 #define MPRIS_H
26 
27 #include <QObject>
28 #include <QPointer>
29 #include <QStringList>
30 #include <QVariantMap>
31 #include <QApplication>
32 #include "mpd-interface/song.h"
33 #include "mpd-interface/mpdstatus.h"
34 #include "gui/stdactions.h"
35 
36 class QDBusObjectPath;
37 
38 class Mpris : public QObject
39 {
40     Q_OBJECT
41 
42     // org.mpris.MediaPlayer2.Player
43     Q_PROPERTY( double Rate READ Rate WRITE SetRate )
44     Q_PROPERTY( qlonglong Position READ Position )
45     Q_PROPERTY( double MinimumRate READ MinimumRate )
46     Q_PROPERTY( double MaximumRate READ MaximumRate )
47     Q_PROPERTY( bool CanControl READ CanControl )
48     Q_PROPERTY( bool CanPlay READ CanPlay )
49     Q_PROPERTY( bool CanPause READ CanPause )
50     Q_PROPERTY( bool CanSeek READ CanSeek )
51     Q_PROPERTY( bool CanGoNext READ CanGoNext )
52     Q_PROPERTY( bool CanGoPrevious READ CanGoPrevious )
53     Q_PROPERTY( QString PlaybackStatus READ PlaybackStatus )
54     Q_PROPERTY( QString LoopStatus READ LoopStatus WRITE SetLoopStatus )
55     Q_PROPERTY( bool Shuffle READ Shuffle WRITE SetShuffle )
56     Q_PROPERTY( QVariantMap Metadata READ Metadata )
57     Q_PROPERTY( double Volume READ Volume WRITE SetVolume )
58 
59     // org.mpris.MediaPlayer2
60     Q_PROPERTY( bool CanQuit READ CanQuit )
61     Q_PROPERTY( bool CanRaise READ CanRaise )
62     Q_PROPERTY( QString DesktopEntry READ DesktopEntry )
63     Q_PROPERTY( bool HasTrackList READ HasTrackList )
64     Q_PROPERTY( QString Identity READ Identity )
65     Q_PROPERTY( QStringList SupportedMimeTypes READ SupportedMimeTypes )
66     Q_PROPERTY( QStringList SupportedUriSchemes READ SupportedUriSchemes )
67 
68 public:
69     Mpris(QObject *p);
70     ~Mpris() override;
71 
72     // org.mpris.MediaPlayer2.Player
Next()73     void Next() { StdActions::self()->nextTrackAction->trigger(); }
Previous()74     void Previous() { StdActions::self()->prevTrackAction->trigger(); }
75     void Pause();
PlayPause()76     void PlayPause() { StdActions::self()->playPauseTrackAction->trigger(); }
Stop()77     void Stop() { StdActions::self()->stopPlaybackAction->trigger(); }
StopAfterCurrent()78     void StopAfterCurrent() { StdActions::self()->stopAfterCurrentTrackAction->trigger(); }
79     void Play();
Seek(qlonglong pos)80     void Seek(qlonglong pos) { emit seek(pos/1000000); }
81     void SetPosition(const QDBusObjectPath &trackId, qlonglong pos);
OpenUri(const QString &)82     void OpenUri(const QString &) { }
83     QString PlaybackStatus() const;
LoopStatus()84     QString LoopStatus() { return (!status.isNull() && status->repeat()) ? (status->single() ? QLatin1String("Track") : QLatin1String("Playlist")) : QLatin1String("None"); }
85     void SetLoopStatus(const QString &s);
86     QVariantMap Metadata() const;
Rate()87     int Rate() const { return 1.0; }
SetRate(double)88     void SetRate(double) { }
Shuffle()89     bool Shuffle() { return !status.isNull() && status->random(); }
SetShuffle(bool s)90     void SetShuffle(bool s) { emit setRandom(s); }
Volume()91     double Volume() const { return status.isNull() ? 0.0 : status->volume()/100.0; }
SetVolume(double v)92     void SetVolume(double v) { emit setVolume(v*100); }
93     qlonglong Position() const;
MinimumRate()94     double MinimumRate() const { return 1.0; }
MaximumRate()95     double MaximumRate() const { return 1.0; }
CanControl()96     bool CanControl() const { return true; }
CanPlay()97     bool CanPlay() const { return !status.isNull() && status->playlistLength()>0; }
CanPause()98     bool CanPause() const { return !status.isNull() && MPDState_Stopped!=status->state() && status->songId()!=-1; }
CanSeek()99     bool CanSeek() const { return !status.isNull() && status->songId()!=-1 && !currentSong.isCdda() && !currentSong.isStandardStream() && currentSong.time>5; }
CanGoNext()100     bool CanGoNext() const { return !status.isNull() && MPDState_Stopped!=status->state() && status->songId()!=-1 && status->nextSongId()!=-1; }
CanGoPrevious()101     bool CanGoPrevious() const { return !status.isNull() && MPDState_Stopped!=status->state() && status->songId()!=-1 && (status->playlistLength()>1 || currentSong.time>5); }
102 
103     // org.mpris.MediaPlayer2
CanQuit()104     bool CanQuit() const { return true; }
CanRaise()105     bool CanRaise() const { return true; }
HasTrackList()106     bool HasTrackList() const { return false; }
Identity()107     QString Identity() const { return QLatin1String("Cantata"); }
DesktopEntry()108     QString DesktopEntry() const { return QLatin1String("cantata"); }
SupportedUriSchemes()109     QStringList SupportedUriSchemes() const { return QStringList(); }
SupportedMimeTypes()110     QStringList SupportedMimeTypes() const { return QStringList(); }
111 
112 public:
113     void updateCurrentSong(const Song &song);
114 
115 public Q_SLOTS:
116     void Raise();
Quit()117     void Quit() { QApplication::quit(); }
118 
119 Q_SIGNALS:
120     // org.mpris.MediaPlayer2.Player
121     void setRandom(bool toggle);
122     void setRepeat(bool toggle);
123     void setSingle(bool toggle);
124     void setSeekId(qint32 songId, quint32 time);
125     void seek(qint32 offset);
126     void setVolume(int vol);
127 
128     void showMainWindow();
129 
130 public Q_SLOTS:
131     void updateCurrentCover(const QString &fileName);
132     void updateStatus(MPDStatus * const status);
133 
134 private Q_SLOTS:
135     void updateStatus();
136 
137 private:
138     void signalUpdate(const QString &property, const QVariant &value);
139     void signalUpdate(const QVariantMap &map);
140     QString currentTrackId() const;
141 
142 private:
143     QPointer<MPDStatus> status;
144     MPDStatusValues lastStatus;
145     QString currentCover;
146     Song currentSong;
147     int pos;
148 };
149 
150 #endif
151