File indexing completed on 2025-02-23 04:34:22
0001 /** 0002 * \file mprisinterface.h 0003 * MPRIS D-Bus interface for audio player. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 09-Dec-2016 0008 * 0009 * Copyright (C) 2016-2024 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #pragma once 0028 0029 #include <QObject> 0030 #include "config.h" 0031 0032 #ifdef HAVE_QTDBUS 0033 0034 #include <QDBusAbstractAdaptor> 0035 #include <QStringList> 0036 0037 class QDBusObjectPath; 0038 class QTemporaryFile; 0039 class AudioPlayer; 0040 0041 /** 0042 * MPRIS D-Bus Interface MediaPlayer2. 0043 * See https://specifications.freedesktop.org/mpris-spec/2.2/ 0044 */ 0045 class MprisInterface : public QDBusAbstractAdaptor { 0046 Q_OBJECT 0047 Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2") 0048 /** false, Quit() is not supported. */ 0049 Q_PROPERTY(bool CanQuit READ canQuit CONSTANT) 0050 /** false, not full screen. */ 0051 Q_PROPERTY(bool Fullscreen READ fullscreen CONSTANT) 0052 /** false, Fullscreen is not supported. */ 0053 Q_PROPERTY(bool CanSetFullscreen READ canSetFullscreen CONSTANT) 0054 /** false, Raise() is not supported. */ 0055 Q_PROPERTY(bool CanRaise READ canRaise CONSTANT) 0056 /** false, org.mpris.MediaPlayer2.TrackList interface is not implemented. */ 0057 Q_PROPERTY(bool HasTrackList READ hasTrackList CONSTANT) 0058 /** Media player identification "Kid3". */ 0059 Q_PROPERTY(QString Identity READ identity CONSTANT) 0060 /** Base name of desktop file "kid3". */ 0061 Q_PROPERTY(QString DesktopEntry READ desktopEntry CONSTANT) 0062 /** URI schemes supported by the media player, ["file"]. */ 0063 Q_PROPERTY(QStringList SupportedUriSchemes READ supportedUriSchemes CONSTANT) 0064 /** MIME types supported by the media player. */ 0065 Q_PROPERTY(QStringList SupportedMimeTypes READ supportedMimeTypes CONSTANT) 0066 0067 public: 0068 /** 0069 * Constructor. 0070 * 0071 * @param player parent audio player 0072 */ 0073 explicit MprisInterface(AudioPlayer* player); 0074 0075 /** 0076 * Destructor. 0077 */ 0078 ~MprisInterface() override = default; 0079 0080 public slots: 0081 /** 0082 * Bring media player to front, not implemented. 0083 */ 0084 void Raise() {} 0085 0086 /** 0087 * Terminate media player, not implemented. 0088 */ 0089 void Quit() {} 0090 0091 private: 0092 bool canQuit() const { return false; } 0093 bool fullscreen() const { return false; } 0094 bool canSetFullscreen() const { return false; } 0095 bool canRaise() const { return false; } 0096 bool hasTrackList() const { return false; } 0097 QString identity() const; 0098 QString desktopEntry() const; 0099 QStringList supportedUriSchemes() const; 0100 QStringList supportedMimeTypes() const; 0101 0102 AudioPlayer* m_audioPlayer; 0103 }; 0104 0105 0106 /** 0107 * MPRIS D-Bus Interface MediaPlayer2.Player. 0108 * See https://specifications.freedesktop.org/mpris-spec/2.2/ 0109 */ 0110 class MprisPlayerInterface : public QDBusAbstractAdaptor { 0111 Q_OBJECT 0112 Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.Player") 0113 /** Playback status, "Playing", "Paused" or "Stopped". */ 0114 Q_PROPERTY(QString PlaybackStatus READ playbackStatus) 0115 /** Loop status, "None". */ 0116 Q_PROPERTY(QString LoopStatus READ loopStatus CONSTANT) 0117 /** Playback rate 1.0. */ 0118 Q_PROPERTY(double Rate READ rate CONSTANT) 0119 /** false, shuffle is not implemented. */ 0120 Q_PROPERTY(bool Shuffle READ shuffle CONSTANT) 0121 /** Map with metadata. */ 0122 Q_PROPERTY(QVariantMap Metadata READ metadata) 0123 /** Current volume, value between 0.0 and 1.0. */ 0124 Q_PROPERTY(double Volume READ volume WRITE setVolume) 0125 /** Current track position in microseconds. */ 0126 Q_PROPERTY(qlonglong Position READ position) 0127 /** Minimum playback rate 1.0. */ 0128 Q_PROPERTY(double MinimumRate READ minimumRate CONSTANT) 0129 /** Maximum playback rate 1.0. */ 0130 Q_PROPERTY(double MaximumRate READ maximumRate CONSTANT) 0131 /** true if there is a next track. */ 0132 Q_PROPERTY(bool CanGoNext READ canGoNext) 0133 /** true if there is a previous track. */ 0134 Q_PROPERTY(bool CanGoPrevious READ canGoPrevious) 0135 /** true if there is a current track. */ 0136 Q_PROPERTY(bool CanPlay READ canPlay) 0137 /** true if there is a current track. */ 0138 Q_PROPERTY(bool CanPause READ canPause) 0139 /** true, Seek() and SetPosition() are implemented. */ 0140 Q_PROPERTY(bool CanSeek READ canSeek) 0141 /** true, media player can be controlled. */ 0142 Q_PROPERTY(bool CanControl READ canControl CONSTANT) 0143 0144 public: 0145 /** 0146 * Constructor. 0147 * 0148 * @param player parent audio player 0149 */ 0150 explicit MprisPlayerInterface(AudioPlayer* player); 0151 0152 /** 0153 * Destructor. 0154 */ 0155 ~MprisPlayerInterface() override; 0156 0157 public slots: 0158 /** 0159 * Skip to next track in tracklist. 0160 */ 0161 void Next(); 0162 0163 /** 0164 * Skip to previous track in tracklist. 0165 */ 0166 void Previous(); 0167 0168 /** 0169 * Pause playback. 0170 */ 0171 void Pause(); 0172 0173 /** 0174 * If playback is paused, resume playback, if playback is stopped, 0175 * start playback. 0176 */ 0177 void PlayPause(); 0178 0179 /** 0180 * Stop playback. 0181 */ 0182 void Stop(); 0183 0184 /** 0185 * Start or resume playback. 0186 */ 0187 void Play(); 0188 0189 /** 0190 * Seek forward in the current track by the specified number of microseconds. 0191 * 0192 * A negative value seeks back. If this would mean seeking back further than 0193 * the start of the track, the position is set to 0. If the value passed in 0194 * would mean seeking beyond the end of the track, acts like a call to Next(). 0195 * 0196 * @param offsetUs microseconds to seek forward 0197 */ 0198 void Seek(qlonglong offsetUs); 0199 0200 /** 0201 * Set the current track position in microseconds. 0202 * 0203 * If @a positionUs is less than 0, do nothing. If @a positionUs is greater 0204 * than the track length, do nothing. 0205 * 0206 * @param trackId the currently playing track's identifier 0207 * @param positionUs track position in microseconds 0208 */ 0209 void SetPosition(const QDBusObjectPath& trackId, qlonglong positionUs); 0210 0211 /** 0212 * Open file. 0213 * @param uri URL of track to load 0214 */ 0215 void OpenUri(const QString& uri); 0216 0217 signals: 0218 /** 0219 * Indicates that the track position has changed in a way that is 0220 * inconsistant with the current playing state. 0221 * @param positionUs new position in microseconds 0222 */ 0223 void Seeked(qlonglong positionUs); 0224 0225 private slots: 0226 void onStateChanged(); 0227 void onTrackChanged(const QString& filePath, bool hasPrevious, bool hasNext); 0228 void onVolumeChanged(); 0229 void onFileCountChanged(int count); 0230 void onCurrentPositionChanged(qint64 position); 0231 0232 private: 0233 QString playbackStatus() const; 0234 QString loopStatus() const { return QLatin1String("None"); } 0235 double rate() const { return 1.0; } 0236 bool shuffle() const { return false; } 0237 QVariantMap metadata() const; 0238 double volume() const; 0239 void setVolume(double volume); 0240 qlonglong position() const; 0241 double minimumRate() const { return 1.0; } 0242 double maximumRate() const { return 1.0; } 0243 bool canGoNext() const; 0244 bool canGoPrevious() const; 0245 bool canPlay() const; 0246 bool canPause() const; 0247 bool canSeek() const { return true; } 0248 bool canControl() const { return true; } 0249 0250 void sendPropertiesChangedSignal(const QString& name, const QVariant& value); 0251 QDBusObjectPath getCurrentTrackId() const; 0252 QString findCoverArtInDirectory(const QString& dirPath) const; 0253 0254 AudioPlayer* m_audioPlayer; 0255 QString m_status; 0256 bool m_hasPrevious; 0257 bool m_hasNext; 0258 bool m_hasFiles; 0259 mutable QTemporaryFile* m_tempCoverArtFile; 0260 mutable QString m_coverArtDirName; 0261 mutable QString m_coverArtFileName; 0262 }; 0263 0264 #else 0265 0266 // Just to suppress moc "No relevant classes found" warning. 0267 class MprisInterface : public QObject { 0268 Q_OBJECT 0269 }; 0270 0271 #endif