File indexing completed on 2024-05-19 05:38:37
0001 /* 0002 SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <QBindable> 0010 #include <QObject> 0011 0012 #include <qqmlregistration.h> 0013 0014 #include "kmpris_export.h" 0015 0016 class QDBusPendingCallWatcher; 0017 0018 class OrgFreedesktopDBusPropertiesInterface; 0019 class OrgMprisMediaPlayer2Interface; 0020 class OrgMprisMediaPlayer2PlayerInterface; 0021 0022 inline constexpr QLatin1String MPRIS2_PATH{"/org/mpris/MediaPlayer2"}; 0023 inline constexpr QLatin1String MPRIS2_PREFIX{"org.mpris.MediaPlayer2."}; 0024 0025 namespace LoopStatus 0026 { 0027 QML_ELEMENT 0028 KMPRIS_EXPORT Q_NAMESPACE // 0029 enum KMPRIS_EXPORT Status : std::uint32_t { 0030 Unknown = 0, 0031 None, 0032 Playlist, 0033 Track, 0034 }; 0035 KMPRIS_EXPORT Q_ENUM_NS(Status) 0036 } 0037 0038 namespace ShuffleStatus 0039 { 0040 QML_ELEMENT 0041 KMPRIS_EXPORT Q_NAMESPACE // 0042 enum KMPRIS_EXPORT Status : std::uint32_t { 0043 Unknown = 0, 0044 Off, 0045 On, 0046 }; 0047 KMPRIS_EXPORT Q_ENUM_NS(Status) 0048 } 0049 0050 namespace PlaybackStatus 0051 { 0052 QML_ELEMENT 0053 KMPRIS_EXPORT Q_NAMESPACE // 0054 enum KMPRIS_EXPORT Status : std::uint32_t { 0055 Unknown = 0, 0056 Stopped, 0057 Playing, 0058 Paused, 0059 }; 0060 KMPRIS_EXPORT Q_ENUM_NS(Status) 0061 } 0062 0063 /** 0064 * A class with empty player information 0065 */ 0066 class KMPRIS_EXPORT AbstractPlayerContainer : public QObject 0067 { 0068 Q_OBJECT 0069 // From org.mpris.MediaPlayer2.Player 0070 Q_PROPERTY(bool canGoNext READ canGoNext NOTIFY canGoNextChanged) 0071 Q_PROPERTY(bool canGoPrevious READ canGoPrevious NOTIFY canGoPreviousChanged) 0072 Q_PROPERTY(bool canPlay READ canPlay NOTIFY canPlayChanged) 0073 Q_PROPERTY(bool canPause READ canPause NOTIFY canPauseChanged) 0074 Q_PROPERTY(bool canStop READ canStop NOTIFY canStopChanged) 0075 Q_PROPERTY(bool canSeek READ canSeek NOTIFY canSeekChanged) 0076 Q_PROPERTY(bool canControl READ canControl NOTIFY canControlChanged) 0077 Q_PROPERTY(LoopStatus::Status loopStatus READ loopStatus NOTIFY loopStatusChanged) 0078 Q_PROPERTY(double maximumRate READ maximumRate NOTIFY maximumRateChanged) 0079 Q_PROPERTY(double minimumRate READ minimumRate NOTIFY minimumRateChanged) 0080 Q_PROPERTY(PlaybackStatus::Status playbackStatus READ playbackStatus NOTIFY playbackStatusChanged) 0081 Q_PROPERTY(qlonglong position READ position NOTIFY positionChanged) 0082 Q_PROPERTY(double rate READ rate NOTIFY rateChanged) 0083 Q_PROPERTY(ShuffleStatus::Status shuffle READ shuffle NOTIFY shuffleChanged) 0084 Q_PROPERTY(double volume READ volume NOTIFY volumeChanged) 0085 0086 // From metadata map 0087 Q_PROPERTY(QString track READ track NOTIFY trackChanged) 0088 Q_PROPERTY(QString artist READ artist NOTIFY artistChanged) 0089 Q_PROPERTY(QString artUrl READ artUrl NOTIFY artUrlChanged) 0090 Q_PROPERTY(QString album READ album NOTIFY albumChanged) 0091 Q_PROPERTY(double length READ length NOTIFY lengthChanged) 0092 0093 /** 0094 * Used to filter p-b-i player 0095 */ 0096 Q_PROPERTY(unsigned kdePid READ kdePid NOTIFY kdePidChanged) 0097 0098 // From org.mpris.MediaPlayer2 0099 Q_PROPERTY(bool canQuit READ canQuit NOTIFY canQuitChanged) 0100 Q_PROPERTY(bool canRaise READ canRaise NOTIFY canRaiseChanged) 0101 Q_PROPERTY(bool canSetFullscreen READ canSetFullscreen NOTIFY canSetFullscreenChanged) 0102 Q_PROPERTY(QStringList supportedMimeTypes READ supportedMimeTypes NOTIFY supportedMimeTypesChanged) 0103 Q_PROPERTY(QStringList supportedUriSchemes READ supportedUriSchemes NOTIFY supportedUriSchemesChanged) 0104 Q_PROPERTY(QString desktopEntry READ desktopEntry NOTIFY desktopEntryChanged) 0105 Q_PROPERTY(QString iconName READ iconName NOTIFY desktopEntryChanged) 0106 Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged) 0107 Q_PROPERTY(bool hasTrackList READ hasTrackList NOTIFY hasTrackListChanged) 0108 Q_PROPERTY(QString identity READ identity NOTIFY identityChanged) 0109 Q_PROPERTY(unsigned instancePid READ instancePid CONSTANT) 0110 0111 public: 0112 explicit AbstractPlayerContainer(QObject *parent = nullptr); 0113 ~AbstractPlayerContainer() override; 0114 0115 bool canControl() const; 0116 bool canGoNext() const; 0117 bool canGoPrevious() const; 0118 bool canPause() const; 0119 bool canPlay() const; 0120 bool canStop() const; 0121 bool canSeek() const; 0122 0123 LoopStatus::Status loopStatus() const; 0124 0125 double maximumRate() const; 0126 double minimumRate() const; 0127 PlaybackStatus::Status playbackStatus() const; 0128 0129 qlonglong position() const; 0130 0131 double rate() const; 0132 0133 ShuffleStatus::Status shuffle() const; 0134 0135 double volume() const; 0136 0137 QString track() const; 0138 QString artist() const; 0139 QString artUrl() const; 0140 QString album() const; 0141 double length() const; 0142 0143 unsigned instancePid() const; 0144 unsigned kdePid() const; 0145 0146 bool canQuit() const; 0147 bool canRaise() const; 0148 bool canSetFullscreen() const; 0149 QString desktopEntry() const; 0150 bool fullscreen() const; 0151 bool hasTrackList() const; 0152 QString identity() const; 0153 QStringList supportedMimeTypes() const; 0154 QStringList supportedUriSchemes() const; 0155 QString iconName() const; 0156 0157 Q_SIGNALS: 0158 void canGoNextChanged(); 0159 void canGoPreviousChanged(); 0160 void canPlayChanged(); 0161 void canPauseChanged(); 0162 void canStopChanged(); 0163 void canSeekChanged(); 0164 void canControlChanged(); 0165 void loopStatusChanged(); 0166 void maximumRateChanged(); 0167 void metadataChanged(); 0168 void minimumRateChanged(); 0169 void playbackStatusChanged(); 0170 void positionChanged(); 0171 void rateChanged(); 0172 void shuffleChanged(); 0173 void volumeChanged(); 0174 0175 void trackChanged(); 0176 void artistChanged(); 0177 void artUrlChanged(); 0178 void albumChanged(); 0179 void lengthChanged(); 0180 void kdePidChanged(); 0181 0182 void canQuitChanged(); 0183 void canSetFullscreenChanged(); 0184 void canRaiseChanged(); 0185 void supportedMimeTypesChanged(); 0186 void supportedUriSchemesChanged(); 0187 void desktopEntryChanged(); 0188 void fullscreenChanged(); 0189 void hasTrackListChanged(); 0190 void identityChanged(); 0191 0192 protected: 0193 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canControl, false, &AbstractPlayerContainer::canControlChanged) 0194 0195 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canGoNext, false) 0196 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_effectiveCanGoNext, false, &AbstractPlayerContainer::canGoNextChanged) 0197 0198 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canGoPrevious, false) 0199 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_effectiveCanGoPrevious, false, &AbstractPlayerContainer::canGoPreviousChanged) 0200 0201 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canPlay, false) 0202 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_effectiveCanPlay, false, &AbstractPlayerContainer::canPlayChanged) 0203 0204 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canPause, false) 0205 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_effectiveCanPause, false, &AbstractPlayerContainer::canPauseChanged) 0206 0207 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canStop, false) 0208 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_effectiveCanStop, false, &AbstractPlayerContainer::canStopChanged) 0209 0210 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canSeek, false, &AbstractPlayerContainer::canSeekChanged) 0211 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_effectiveCanSeek, false, &AbstractPlayerContainer::canSeekChanged) 0212 0213 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, 0214 LoopStatus::Status, 0215 m_loopStatus, 0216 LoopStatus::Unknown, 0217 &AbstractPlayerContainer::loopStatusChanged) 0218 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, 0219 ShuffleStatus::Status, 0220 m_shuffle, 0221 ShuffleStatus::Unknown, 0222 &AbstractPlayerContainer::shuffleChanged) 0223 0224 // From metadata 0225 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QString, m_trackId) 0226 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QString, m_xesamTitle) 0227 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QString, m_xesamUrl) 0228 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QString, m_xesamAlbum) 0229 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QStringList, m_xesamArtist) 0230 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QStringList, m_xesamAlbumArtist) 0231 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QString, m_track, &AbstractPlayerContainer::trackChanged) 0232 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QString, m_artist, &AbstractPlayerContainer::artistChanged) 0233 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QString, m_artUrl, &AbstractPlayerContainer::artUrlChanged) 0234 Q_OBJECT_BINDABLE_PROPERTY(AbstractPlayerContainer, QString, m_album, &AbstractPlayerContainer::albumChanged) 0235 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, double, m_length, 0.0, &AbstractPlayerContainer::lengthChanged) 0236 0237 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, double, m_minimumRate, 0.0, &AbstractPlayerContainer::minimumRateChanged) 0238 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, double, m_maximumRate, 0.0, &AbstractPlayerContainer::maximumRateChanged) 0239 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, 0240 PlaybackStatus::Status, 0241 m_playbackStatus, 0242 PlaybackStatus::Unknown, 0243 &AbstractPlayerContainer::playbackStatusChanged) 0244 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, qlonglong, m_position, 0, &AbstractPlayerContainer::positionChanged) 0245 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, double, m_rate, 1.0, &AbstractPlayerContainer::rateChanged) 0246 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, double, m_volume, 0.0, &AbstractPlayerContainer::volumeChanged) 0247 0248 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canQuit, false, &AbstractPlayerContainer::canQuitChanged) 0249 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canRaise, false, &AbstractPlayerContainer::canRaiseChanged) 0250 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_canSetFullscreen, false, &AbstractPlayerContainer::canSetFullscreenChanged) 0251 QStringList m_supportedMimeTypes; 0252 QStringList m_supportedUriSchemes; 0253 QString m_desktopEntry; 0254 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_fullscreen, false, &AbstractPlayerContainer::fullscreenChanged) 0255 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, bool, m_hasTrackList, false, &AbstractPlayerContainer::hasTrackListChanged) 0256 QString m_identity; 0257 0258 QString m_iconName; 0259 unsigned m_instancePid = 0; 0260 Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(AbstractPlayerContainer, unsigned, m_kdePid, 0, &AbstractPlayerContainer::kdePidChanged) 0261 }; 0262 0263 /** 0264 * A proxy class for the 3 MPRIS2 D-Bus interfaces 0265 */ 0266 class KMPRIS_EXPORT PlayerContainer : public AbstractPlayerContainer 0267 { 0268 Q_OBJECT 0269 QML_ANONYMOUS 0270 0271 Q_PROPERTY(LoopStatus::Status loopStatus READ loopStatus WRITE setLoopStatus NOTIFY loopStatusChanged) 0272 Q_PROPERTY(qlonglong position READ position WRITE setPosition NOTIFY positionChanged) 0273 Q_PROPERTY(double rate READ rate WRITE setRate NOTIFY rateChanged) 0274 Q_PROPERTY(ShuffleStatus::Status shuffle READ shuffle WRITE setShuffle NOTIFY shuffleChanged) 0275 Q_PROPERTY(double volume READ volume WRITE setVolume NOTIFY volumeChanged) 0276 Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged) 0277 Q_PROPERTY(PlaybackStatus::Status playbackStatus READ playbackStatus WRITE setPlaybackStatus NOTIFY playbackStatusChanged) 0278 0279 public: 0280 explicit PlayerContainer(const QString &busAddress, QObject *parent = nullptr); 0281 ~PlayerContainer() override; 0282 0283 QString dbusAddress() const 0284 { 0285 return m_dbusAddress; 0286 } 0287 0288 void setLoopStatus(LoopStatus::Status value); 0289 void setPosition(qlonglong value); 0290 void setRate(double value); 0291 void setShuffle(ShuffleStatus::Status value); 0292 void setVolume(double value); 0293 void setFullscreen(bool value); 0294 void setPlaybackStatus(PlaybackStatus::Status value); 0295 0296 Q_INVOKABLE void Next(); 0297 Q_INVOKABLE void OpenUri(const QString &Uri); 0298 Q_INVOKABLE void Pause(); 0299 Q_INVOKABLE void Play(); 0300 Q_INVOKABLE void PlayPause(); 0301 Q_INVOKABLE void Previous(); 0302 Q_INVOKABLE void Seek(qlonglong Offset); 0303 Q_INVOKABLE void Stop(); 0304 Q_INVOKABLE void Quit(); 0305 Q_INVOKABLE void Raise(); 0306 0307 void refresh(); 0308 0309 Q_INVOKABLE void updatePosition(); 0310 Q_INVOKABLE void changeVolume(double delta, bool showOSD); 0311 0312 Q_SIGNALS: 0313 void initialFetchFinished(PlayerContainer *container); 0314 void initialFetchFailed(PlayerContainer *container); 0315 0316 private Q_SLOTS: 0317 void onGetPropsFinished(QDBusPendingCallWatcher *watcher); 0318 void onPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, const QStringList &invalidatedProperties); 0319 void onSeeked(qlonglong position); 0320 0321 private: 0322 void initBindings(); 0323 void updateFromMap(const QVariantMap &map); 0324 0325 int m_fetchesPending = 0; 0326 QString m_dbusAddress; 0327 OrgFreedesktopDBusPropertiesInterface *m_propsIface = nullptr; 0328 OrgMprisMediaPlayer2PlayerInterface *m_playerIface = nullptr; 0329 OrgMprisMediaPlayer2Interface *m_rootIface = nullptr; 0330 0331 QPropertyNotifier m_rateNotifier; 0332 QPropertyNotifier m_playbackStatusNotifier; 0333 };