[OpenDocString] kdeconnect-kde (cpp)
mprisremoteplayermediaplayer2player.cpp
MprisRemotePlayerMediaPlayer2Player::MprisRemotePlayerMediaPlayer2Player(MprisRemotePlayer *parent, MprisRemotePlugin *plugin)
    : QDBusAbstractAdaptor{parent}
    , m_parent{parent}
    , m_plugin{plugin}
    , m_controlsChanged{false}
    , m_trackInfoChanged{false}
    , m_positionChanged{false}
    , m_volumeChanged{false}
    , m_playingChanged{false}
{
    connect(m_parent, &MprisRemotePlayer::controlsChanged, this, &MprisRemotePlayerMediaPlayer2Player::controlsChanged);
    connect(m_parent, &MprisRemotePlayer::trackInfoChanged, this, &MprisRemotePlayerMediaPlayer2Player::trackInfoChanged);
    connect(m_parent, &MprisRemotePlayer::positionChanged, this, &MprisRemotePlayerMediaPlayer2Player::positionChanged);
    connect(m_parent, &MprisRemotePlayer::volumeChanged, this, &MprisRemotePlayerMediaPlayer2Player::volumeChanged);
    connect(m_parent, &MprisRemotePlayer::playingChanged, this, &MprisRemotePlayerMediaPlayer2Player::playingChanged);
}
This constructor builds a media player2player object from an existing parent. It allows to manage signals for the position and volume of the remote player and the plugin.
MprisRemotePlayerMediaPlayer2Player::~MprisRemotePlayerMediaPlayer2Player() = default;
This removes the media player2player reference from the list of available media players.
QString MprisRemotePlayerMediaPlayer2Player::PlaybackStatus() const
{
    if (m_parent->playing()) {
        return QStringLiteral("Playing");
    } else {
        return QStringLiteral("Paused");
    }
}
Returns the playback status as a QString.
double MprisRemotePlayerMediaPlayer2Player::Rate() const
{
    return 1.0;
}
Returns the rate in kilobytes.
QVariantMap MprisRemotePlayerMediaPlayer2Player::Metadata() const
{
    QVariantMap metadata;
    metadata[QStringLiteral("mpris:trackid")] = QVariant::fromValue(QDBusObjectPath("/org/mpris/MediaPlayer2"));

    if (m_parent->length() > 0) {
        metadata[QStringLiteral("mpris:length")] = QVariant::fromValue(m_parent->length() * qlonglong(1000));
    }
    if (!m_parent->title().isEmpty()) {
        metadata[QStringLiteral("xesam:title")] = m_parent->title();
    }
    if (!m_parent->artist().isEmpty()) {
        metadata[QStringLiteral("xesam:artist")] = QStringList{m_parent->artist()};
    }
    if (!m_parent->album().isEmpty()) {
        metadata[QStringLiteral("xesam:album")] = m_parent->album();
    }
    return metadata;
}
This retrieves the metadata for the media player from the mpris. The function first constructs the metadata map from the parent object, and adds it to the metadata. Then, the function retrieves the metadata for the parent object, and checks for empty values.
double MprisRemotePlayerMediaPlayer2Player::Volume() const
{
    return m_parent->volume() / 100.0;
}
Returns the volume in percent.
void MprisRemotePlayerMediaPlayer2Player::setVolume(double volume) const
{
    m_plugin->setPlayer(m_parent->identity());
    m_plugin->setVolume(volume * 100.0 + 0.5);
}
Sets the volume value within 0. 5% of the parent player.
qlonglong MprisRemotePlayerMediaPlayer2Player::Position() const
{
    return m_plugin->position() * qlonglong(1000);
}
Returns the current position in milliseconds.
double MprisRemotePlayerMediaPlayer2Player::MinimumRate() const
{
    return 1.0;
}
Returns the minimum rate in the current media stream.
double MprisRemotePlayerMediaPlayer2Player::MaximumRate() const
{
    return 1.0;
}
Returns the maximum rate allowed by the remote player.
bool MprisRemotePlayerMediaPlayer2Player::CanGoNext() const
{
    return m_parent->canGoNext();
}
This implements checking if the parent can go the next item.
bool MprisRemotePlayerMediaPlayer2Player::CanGoPrevious() const
{
    return m_parent->canGoPrevious();
}
This implements checking if the parent can go previous.
bool MprisRemotePlayerMediaPlayer2Player::CanPlay() const
{
    return m_parent->canPlay();
}
This implements checking if the parent can play the media.
bool MprisRemotePlayerMediaPlayer2Player::CanPause() const
{
    return m_parent->canPause();
}
This implements checking if the parent can handle pause.
bool MprisRemotePlayerMediaPlayer2Player::CanSeek() const
{
    return m_parent->canSeek();
}
This implements checking if the parent can seek.
bool MprisRemotePlayerMediaPlayer2Player::CanControl() const
{
    return true;
}
This implements checking if the remote player can control the video.
void MprisRemotePlayerMediaPlayer2Player::Next()
{
    m_plugin->setPlayer(m_parent->identity());
    m_plugin->sendAction(QStringLiteral("Next"));
}
This sends the next action to the parent player.
void MprisRemotePlayerMediaPlayer2Player::Previous()
{
    m_plugin->setPlayer(m_parent->identity());
    m_plugin->sendAction(QStringLiteral("Previous"));
}
This sends a previous action to the parent player.
void MprisRemotePlayerMediaPlayer2Player::Pause()
{
    m_plugin->setPlayer(m_parent->identity());
    m_plugin->sendAction(QStringLiteral("Pause"));
}
Sets the player to the parent identity, and sends a pause action.
void MprisRemotePlayerMediaPlayer2Player::PlayPause()
{
    m_plugin->setPlayer(m_parent->identity());
    m_plugin->sendAction(QStringLiteral("PlayPause"));
}
This sends a playpause action to the parent player.
void MprisRemotePlayerMediaPlayer2Player::Stop()
{
    m_plugin->setPlayer(m_parent->identity());
    m_plugin->sendAction(QStringLiteral("Stop"));
}
This sends a stop signal to the media player2player plugin.
void MprisRemotePlayerMediaPlayer2Player::Play()
{
    m_plugin->setPlayer(m_parent->identity());
    m_plugin->sendAction(QStringLiteral("Play"));
}
Sets the player identity to the parent object, and sends the play action.
void MprisRemotePlayerMediaPlayer2Player::Seek(qlonglong Offset)
{
    m_plugin->setPlayer(m_parent->identity());
    m_plugin->seek(Offset);
}
Sets the current position of the media player to the given offset.
void MprisRemotePlayerMediaPlayer2Player::SetPosition(QDBusObjectPath TrackId, qlonglong Position)
{
    Q_UNUSED(TrackId)

    m_plugin->setPlayer(m_parent->identity());
    m_plugin->setPosition(Position / 1000);
}
Sets the position of the media player by setting its position in milliseconds.
void MprisRemotePlayerMediaPlayer2Player::controlsChanged()
{
    m_controlsChanged = true;
    QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
}
This emits the properties changed signal on the media player2player object.
void MprisRemotePlayerMediaPlayer2Player::playingChanged()
{
    m_playingChanged = true;
    QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
}
This emits the properties changed signal on the media player2player object.
void MprisRemotePlayerMediaPlayer2Player::positionChanged()
{
    m_positionChanged = true;
    QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
}
This emits the properties changed signal on the media player2 player object.
void MprisRemotePlayerMediaPlayer2Player::trackInfoChanged()
{
    m_trackInfoChanged = true;
    QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
}
This emits the properties changed signal on the media player2player object.
void MprisRemotePlayerMediaPlayer2Player::volumeChanged()
{
    m_volumeChanged = true;
    QMetaObject::invokeMethod(this, &MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged, Qt::QueuedConnection);
}
This emits the properties changed signal on the media player2player object.
void MprisRemotePlayerMediaPlayer2Player::emitPropertiesChanged()
{
    // Always invoked "queued", so we can send all changes at once
    // Check if things really changed (we might get called multiple times)
    if (!m_controlsChanged && !m_trackInfoChanged && !m_positionChanged && !m_volumeChanged && !m_playingChanged)
        return;

    // Qt doesn't automatically send the "org.freedesktop.DBus.Properties PropertiesChanged" signal, so do it manually
    // With the current setup, it's hard to discover what properties changed. So just send all properties (not too large, usually)
    QVariantMap properties;
    if (m_trackInfoChanged) {
        properties[QStringLiteral("Metadata")] = Metadata();
    }
    if (m_trackInfoChanged || m_positionChanged) {
        properties[QStringLiteral("Position")] = Position();
    }

    if (m_controlsChanged) {
        properties[QStringLiteral("CanGoNext")] = CanGoNext();
        properties[QStringLiteral("CanGoPrevious")] = CanGoPrevious();
        properties[QStringLiteral("CanPlay")] = CanPlay();
        properties[QStringLiteral("CanPause")] = CanPause();
        properties[QStringLiteral("CanSeek")] = CanSeek();
    }

    if (m_playingChanged) {
        properties[QStringLiteral("PlaybackStatus")] = PlaybackStatus();
    }

    if (m_volumeChanged) {
        properties[QStringLiteral("Volume")] = Volume();
    }

    QList args;
    args.push_back(QVariant(QStringLiteral("org.mpris.MediaPlayer2.Player")));
    args.push_back(properties);
    args.push_back(QStringList{});
    QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/org/mpris/MediaPlayer2"),
                                                      QStringLiteral("org.freedesktop.DBus.Properties"),
                                                      QStringLiteral("PropertiesChanged"));
    message.setArguments(args);
    // Send it over the correct DBus connection
    m_parent->dbus().send(message);

    if (m_positionChanged) {
        Q_EMIT Seeked(Position());
    }

    m_controlsChanged = false;
    m_trackInfoChanged = false;
    m_playingChanged = false;
    m_positionChanged = false;
    m_volumeChanged = false;
}
This sends a QDBusMessage object to the MediaPlayer2 player when it gets changes. It checks if things really changed, if it doesn't, it makes it so it will send all the changes. If the m_trackInfoChanged and m_positionChanged parameters are true, it will emit a signal called org.freedesktop.DBus.Properties PropertiesChanged.