File indexing completed on 2024-04-14 04:51:47

0001 /**
0002  * SPDX-FileCopyrightText: 2019 Matthijs Tijink <matthijstijink@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "mprisremoteplayermediaplayer2player.h"
0008 #include "mprisremoteplayer.h"
0009 #include "mprisremoteplugin.h"
0010 
0011 #include <QDBusMessage>
0012 
0013 MprisRemotePlayerMediaPlayer2Player::MprisRemotePlayerMediaPlayer2Player(MprisRemotePlayer *parent, MprisRemotePlugin *plugin)
0014     : QDBusAbstractAdaptor{parent}
0015     , m_parent{parent}
0016     , m_plugin{plugin}
0017     , m_controlsChanged{false}
0018     , m_trackInfoChanged{false}
0019     , m_positionChanged{false}
0020     , m_volumeChanged{false}
0021     , m_playingChanged{false}
0022 {
0023     connect(m_parent, &MprisRemotePlayer::controlsChanged, this, &MprisRemotePlayerMediaPlayer2Player::controlsChanged);
0024     connect(m_parent, &MprisRemotePlayer::trackInfoChanged, this, &MprisRemotePlayerMediaPlayer2Player::trackInfoChanged);
0025     connect(m_parent, &MprisRemotePlayer::positionChanged, this, &MprisRemotePlayerMediaPlayer2Player::positionChanged);
0026     connect(m_parent, &MprisRemotePlayer::volumeChanged, this, &MprisRemotePlayerMediaPlayer2Player::volumeChanged);
0027     connect(m_parent, &MprisRemotePlayer::playingChanged, this, &MprisRemotePlayerMediaPlayer2Player::playingChanged);
0028 }
0029 
0030 QString MprisRemotePlayerMediaPlayer2Player::PlaybackStatus() const
0031 {
0032     if (m_parent->playing()) {
0033         return QStringLiteral("Playing");
0034     } else {
0035         return QStringLiteral("Paused");
0036     }
0037 }
0038 
0039 double MprisRemotePlayerMediaPlayer2Player::Rate() const
0040 {
0041     return 1.0;
0042 }
0043 
0044 QVariantMap MprisRemotePlayerMediaPlayer2Player::Metadata() const
0045 {
0046     QVariantMap metadata;
0047     metadata[QStringLiteral("mpris:trackid")] = QVariant::fromValue<QDBusObjectPath>(QDBusObjectPath("/org/mpris/MediaPlayer2"));
0048 
0049     if (m_parent->length() > 0) {
0050         metadata[QStringLiteral("mpris:length")] = QVariant::fromValue<qlonglong>(m_parent->length() * qlonglong(1000));
0051     }
0052     if (!m_parent->title().isEmpty()) {
0053         metadata[QStringLiteral("xesam:title")] = m_parent->title();
0054     }
0055     if (!m_parent->artist().isEmpty()) {
0056         metadata[QStringLiteral("xesam:artist")] = QStringList{m_parent->artist()};
0057     }
0058     if (!m_parent->album().isEmpty()) {
0059         metadata[QStringLiteral("xesam:album")] = m_parent->album();
0060     }
0061     return metadata;
0062 }
0063 
0064 double MprisRemotePlayerMediaPlayer2Player::Volume() const
0065 {
0066     return m_parent->volume() / 100.0;
0067 }
0068 
0069 void MprisRemotePlayerMediaPlayer2Player::setVolume(double volume) const
0070 {
0071     m_plugin->setPlayer(m_parent->identity());
0072     m_plugin->setVolume(volume * 100.0 + 0.5);
0073 }
0074 
0075 qlonglong MprisRemotePlayerMediaPlayer2Player::Position() const
0076 {
0077     return m_plugin->position() * qlonglong(1000);
0078 }
0079 
0080 double MprisRemotePlayerMediaPlayer2Player::MinimumRate() const
0081 {
0082     return 1.0;
0083 }
0084 
0085 double MprisRemotePlayerMediaPlayer2Player::MaximumRate() const
0086 {
0087     return 1.0;
0088 }
0089 
0090 bool MprisRemotePlayerMediaPlayer2Player::CanGoNext() const
0091 {
0092     return m_parent->canGoNext();
0093 }
0094 
0095 bool MprisRemotePlayerMediaPlayer2Player::CanGoPrevious() const
0096 {
0097     return m_parent->canGoPrevious();
0098 }
0099 
0100 bool MprisRemotePlayerMediaPlayer2Player::CanPlay() const
0101 {
0102     return m_parent->canPlay();
0103 }
0104 
0105 bool MprisRemotePlayerMediaPlayer2Player::CanPause() const
0106 {
0107     return m_parent->canPause();
0108 }
0109 
0110 bool MprisRemotePlayerMediaPlayer2Player::CanSeek() const
0111 {
0112     return m_parent->canSeek();
0113 }
0114 
0115 bool MprisRemotePlayerMediaPlayer2Player::CanControl() const
0116 {
0117     return true;
0118 }
0119 
0120 void MprisRemotePlayerMediaPlayer2Player::Next()
0121 {
0122     m_plugin->setPlayer(m_parent->identity());
0123     m_plugin->sendAction(QStringLiteral("Next"));
0124 }
0125 
0126 void MprisRemotePlayerMediaPlayer2Player::Previous()
0127 {
0128     m_plugin->setPlayer(m_parent->identity());
0129     m_plugin->sendAction(QStringLiteral("Previous"));
0130 }
0131 
0132 void MprisRemotePlayerMediaPlayer2Player::Pause()
0133 {
0134     m_plugin->setPlayer(m_parent->identity());
0135     m_plugin->sendAction(QStringLiteral("Pause"));
0136 }
0137 
0138 void MprisRemotePlayerMediaPlayer2Player::PlayPause()
0139 {
0140     m_plugin->setPlayer(m_parent->identity());
0141     m_plugin->sendAction(QStringLiteral("PlayPause"));
0142 }
0143 
0144 void MprisRemotePlayerMediaPlayer2Player::Stop()
0145 {
0146     m_plugin->setPlayer(m_parent->identity());
0147     m_plugin->sendAction(QStringLiteral("Stop"));
0148 }
0149 
0150 void MprisRemotePlayerMediaPlayer2Player::Play()
0151 {
0152     m_plugin->setPlayer(m_parent->identity());
0153     m_plugin->sendAction(QStringLiteral("Play"));
0154 }
0155 
0156 void MprisRemotePlayerMediaPlayer2Player::Seek(qlonglong Offset)
0157 {
0158     m_plugin->setPlayer(m_parent->identity());
0159     m_plugin->seek(Offset);
0160 }
0161 
0162 void MprisRemotePlayerMediaPlayer2Player::SetPosition(QDBusObjectPath /*TrackId*/, qlonglong Position)
0163 {
0164     m_plugin->setPlayer(m_parent->identity());
0165     m_plugin->setPosition(Position / 1000);
0166 }
0167 
0168 void MprisRemotePlayerMediaPlayer2Player::OpenUri(QString /*Uri*/)
0169 {
0170 }
0171 
0172 void MprisRemotePlayerMediaPlayer2Player::controlsChanged()
0173 {
0174     m_controlsChanged = true;
0175     QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
0176 }
0177 
0178 void MprisRemotePlayerMediaPlayer2Player::playingChanged()
0179 {
0180     m_playingChanged = true;
0181     QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
0182 }
0183 
0184 void MprisRemotePlayerMediaPlayer2Player::positionChanged()
0185 {
0186     m_positionChanged = true;
0187     QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
0188 }
0189 
0190 void MprisRemotePlayerMediaPlayer2Player::trackInfoChanged()
0191 {
0192     m_trackInfoChanged = true;
0193     QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
0194 }
0195 
0196 void MprisRemotePlayerMediaPlayer2Player::volumeChanged()
0197 {
0198     m_volumeChanged = true;
0199     QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
0200 }
0201 
0202 void MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged()
0203 {
0204     // Always invoked "queued", so we can send all changes at once
0205     // Check if things really changed (we might get called multiple times)
0206     if (!m_controlsChanged && !m_trackInfoChanged && !m_positionChanged && !m_volumeChanged && !m_playingChanged)
0207         return;
0208 
0209     // Qt doesn't automatically send the "org.freedesktop.DBus.Properties PropertiesChanged" signal, so do it manually
0210     // With the current setup, it's hard to discover what properties changed. So just send all properties (not too large, usually)
0211     QVariantMap properties;
0212     if (m_trackInfoChanged) {
0213         properties[QStringLiteral("Metadata")] = Metadata();
0214     }
0215     if (m_trackInfoChanged || m_positionChanged) {
0216         properties[QStringLiteral("Position")] = Position();
0217     }
0218 
0219     if (m_controlsChanged) {
0220         properties[QStringLiteral("CanGoNext")] = CanGoNext();
0221         properties[QStringLiteral("CanGoPrevious")] = CanGoPrevious();
0222         properties[QStringLiteral("CanPlay")] = CanPlay();
0223         properties[QStringLiteral("CanPause")] = CanPause();
0224         properties[QStringLiteral("CanSeek")] = CanSeek();
0225     }
0226 
0227     if (m_playingChanged) {
0228         properties[QStringLiteral("PlaybackStatus")] = PlaybackStatus();
0229     }
0230 
0231     if (m_volumeChanged) {
0232         properties[QStringLiteral("Volume")] = Volume();
0233     }
0234 
0235     QList<QVariant> args;
0236     args.push_back(QVariant(QStringLiteral("org.mpris.MediaPlayer2.Player")));
0237     args.push_back(properties);
0238     args.push_back(QStringList{});
0239     QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/org/mpris/MediaPlayer2"),
0240                                                       QStringLiteral("org.freedesktop.DBus.Properties"),
0241                                                       QStringLiteral("PropertiesChanged"));
0242     message.setArguments(args);
0243     // Send it over the correct DBus connection
0244     m_parent->dbus().send(message);
0245 
0246     if (m_positionChanged || m_trackInfoChanged) {
0247         Q_EMIT Seeked(Position());
0248     }
0249 
0250     m_controlsChanged = false;
0251     m_trackInfoChanged = false;
0252     m_playingChanged = false;
0253     m_positionChanged = false;
0254     m_volumeChanged = false;
0255 }
0256 
0257 #include "moc_mprisremoteplayermediaplayer2player.cpp"