File indexing completed on 2024-04-21 08:46:33

0001 /**
0002  * SPDX-FileCopyrightText: 2018 Nicolas Fella <nicolas.fella@gmx.de>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "mprisremoteplayer.h"
0008 #include "mprisremoteplayermediaplayer2.h"
0009 #include "mprisremoteplayermediaplayer2player.h"
0010 #include "mprisremoteplugin.h"
0011 
0012 #include <QDateTime>
0013 
0014 #include <QUuid>
0015 #include <networkpacket.h>
0016 
0017 MprisRemotePlayer::MprisRemotePlayer(QString id, MprisRemotePlugin *plugin)
0018     : QObject(plugin)
0019     , id(id)
0020     , m_playing(false)
0021     , m_canPlay(true)
0022     , m_canPause(true)
0023     , m_canGoPrevious(true)
0024     , m_canGoNext(true)
0025     , m_volume(50)
0026     , m_length(0)
0027     , m_lastPosition(0)
0028     , m_lastPositionTime()
0029     , m_title()
0030     , m_artist()
0031     , m_album()
0032     , m_canSeek(false)
0033     , m_dbusConnectionName(QStringLiteral("mpris_") + QUuid::createUuid().toString(QUuid::Id128))
0034     , m_dbusConnection(QDBusConnection::connectToBus(QDBusConnection::SessionBus, m_dbusConnectionName))
0035 {
0036     // Expose this player on the newly created connection. This allows multiple mpris services in the same Qt process
0037     new MprisRemotePlayerMediaPlayer2(this, plugin);
0038     new MprisRemotePlayerMediaPlayer2Player(this, plugin);
0039 
0040     m_dbusConnection.registerObject(QStringLiteral("/org/mpris/MediaPlayer2"), this);
0041     // Make sure our service name is unique. Reuse the connection name for this.
0042     m_dbusConnection.registerService(QStringLiteral("org.mpris.MediaPlayer2.kdeconnect.") + m_dbusConnectionName);
0043 }
0044 
0045 MprisRemotePlayer::~MprisRemotePlayer()
0046 {
0047     // Drop the DBus connection (it was only used for this class)
0048     QDBusConnection::disconnectFromBus(m_dbusConnectionName);
0049 }
0050 
0051 void MprisRemotePlayer::parseNetworkPacket(const NetworkPacket &np)
0052 {
0053     bool trackInfoHasChanged = false;
0054 
0055     // Track properties
0056     QString newTitle = np.get<QString>(QStringLiteral("title"), m_title);
0057     QString newArtist = np.get<QString>(QStringLiteral("artist"), m_artist);
0058     QString newAlbum = np.get<QString>(QStringLiteral("album"), m_album);
0059     int newLength = np.get<int>(QStringLiteral("length"), m_length);
0060 
0061     // Check if they changed
0062     if (newTitle != m_title || newArtist != m_artist || newAlbum != m_album || newLength != m_length) {
0063         trackInfoHasChanged = true;
0064         m_title = newTitle;
0065         m_artist = newArtist;
0066         m_album = newAlbum;
0067         m_length = newLength;
0068         Q_EMIT trackInfoChanged();
0069     }
0070 
0071     // Check volume changes
0072     int newVolume = np.get<int>(QStringLiteral("volume"), m_volume);
0073     if (newVolume != m_volume) {
0074         m_volume = newVolume;
0075         Q_EMIT volumeChanged();
0076     }
0077 
0078     if (np.has(QStringLiteral("pos"))) {
0079         // Check position
0080         int newLastPosition = np.get<int>(QStringLiteral("pos"), m_lastPosition);
0081         int positionDiff = qAbs(position() - newLastPosition);
0082         m_lastPosition = newLastPosition;
0083         m_lastPositionTime = QDateTime::currentMSecsSinceEpoch();
0084 
0085         // Only consider it seeking if the position changed more than 1 second or the track has changed
0086         if (qAbs(positionDiff) >= 1000 || trackInfoHasChanged) {
0087             Q_EMIT positionChanged();
0088         }
0089     }
0090 
0091     // Check if we started/stopped playing
0092     bool newPlaying = np.get<bool>(QStringLiteral("isPlaying"), m_playing);
0093     if (newPlaying != m_playing) {
0094         m_playing = newPlaying;
0095         Q_EMIT playingChanged();
0096     }
0097 
0098     // Control properties
0099     bool newCanSeek = np.get<bool>(QStringLiteral("canSeek"), m_canSeek);
0100     bool newCanPlay = np.get<bool>(QStringLiteral("canPlay"), m_canPlay);
0101     bool newCanPause = np.get<bool>(QStringLiteral("canPause"), m_canPause);
0102     bool newCanGoPrevious = np.get<bool>(QStringLiteral("canGoPrevious"), m_canGoPrevious);
0103     bool newCanGoNext = np.get<bool>(QStringLiteral("canGoNext"), m_canGoNext);
0104     if (newCanSeek != m_canSeek || newCanPlay != m_canPlay || newCanPause != m_canPause || newCanGoPrevious != m_canGoPrevious || newCanGoNext != m_canGoNext) {
0105         m_canSeek = newCanSeek;
0106         m_canPlay = newCanPlay;
0107         m_canPause = newCanPause;
0108         m_canGoPrevious = newCanGoPrevious;
0109         m_canGoNext = newCanGoNext;
0110         Q_EMIT controlsChanged();
0111     }
0112 }
0113 
0114 long MprisRemotePlayer::position() const
0115 {
0116     if (m_playing) {
0117         return m_lastPosition + (QDateTime::currentMSecsSinceEpoch() - m_lastPositionTime);
0118     } else {
0119         return m_lastPosition;
0120     }
0121 }
0122 
0123 void MprisRemotePlayer::setPosition(long position)
0124 {
0125     m_lastPosition = position;
0126     m_lastPositionTime = QDateTime::currentMSecsSinceEpoch();
0127 }
0128 
0129 int MprisRemotePlayer::volume() const
0130 {
0131     return m_volume;
0132 }
0133 
0134 long int MprisRemotePlayer::length() const
0135 {
0136     return m_length;
0137 }
0138 
0139 bool MprisRemotePlayer::playing() const
0140 {
0141     return m_playing;
0142 }
0143 
0144 QString MprisRemotePlayer::title() const
0145 {
0146     return m_title;
0147 }
0148 
0149 QString MprisRemotePlayer::artist() const
0150 {
0151     return m_artist;
0152 }
0153 
0154 QString MprisRemotePlayer::album() const
0155 {
0156     return m_album;
0157 }
0158 
0159 bool MprisRemotePlayer::canSeek() const
0160 {
0161     return m_canSeek;
0162 }
0163 
0164 QString MprisRemotePlayer::identity() const
0165 {
0166     return id;
0167 }
0168 
0169 bool MprisRemotePlayer::canPlay() const
0170 {
0171     return m_canPlay;
0172 }
0173 
0174 bool MprisRemotePlayer::canPause() const
0175 {
0176     return m_canPause;
0177 }
0178 
0179 bool MprisRemotePlayer::canGoPrevious() const
0180 {
0181     return m_canGoPrevious;
0182 }
0183 
0184 bool MprisRemotePlayer::canGoNext() const
0185 {
0186     return m_canGoNext;
0187 }
0188 
0189 QDBusConnection &MprisRemotePlayer::dbus()
0190 {
0191     return m_dbusConnection;
0192 }
0193 
0194 #include "moc_mprisremoteplayer.cpp"