diff --git a/dataengines/mpris2/playercontrol.cpp b/dataengines/mpris2/playercontrol.cpp --- a/dataengines/mpris2/playercontrol.cpp +++ b/dataengines/mpris2/playercontrol.cpp @@ -27,6 +27,8 @@ #include #include +#include +#include PlayerControl::PlayerControl(PlayerContainer* container, QObject* parent) : Plasma::Service(parent) @@ -90,29 +92,48 @@ m_container = nullptr; } -void PlayerControl::changeVolume(double delta, bool showOSD) { - const double volume = playerInterface()->volume(); - const double newVolume = qBound(0.0, volume + delta, qMax(volume, 1.0)); - playerInterface()->setVolume(newVolume); - - if (showOSD) { - const auto& data = m_container->data(); - - QDBusMessage msg = QDBusMessage::createMethodCall( - QStringLiteral("org.kde.plasmashell"), - QStringLiteral("/org/kde/osdService"), - QStringLiteral("org.kde.osdService"), - QStringLiteral("mediaPlayerVolumeChanged") - ); +void PlayerControl::changeVolume(double delta, bool showOSD) +{ + // Not relying on property/setProperty to avoid doing blocking DBus calls - msg.setArguments({ - (int)(100 * newVolume), - data.value("Identity", ""), - data.value("Desktop Icon Name", "") - }); + const double volume = m_container->data().value(QStringLiteral("Volume")).toDouble(); + const double newVolume = qBound(0.0, volume + delta, qMax(volume, 1.0)); - QDBusConnection::sessionBus().asyncCall(msg); - } + QDBusPendingCall reply = propertiesInterface()->Set(m_container->playerInterface()->interface(), + QStringLiteral("Volume"), QDBusVariant(newVolume)); + + // Update the container value right away so when calling this method in quick succession + // (mouse wheeling the tray icon) next call already gets the new value + m_container->setData(QStringLiteral("Volume"), newVolume); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, [this, showOSD](QDBusPendingCallWatcher *watcher) { + watcher->deleteLater(); + + QDBusPendingReply reply = *watcher; + if (reply.isError()) { + return; + } + + if (showOSD) { + const auto& data = m_container->data(); + + QDBusMessage msg = QDBusMessage::createMethodCall( + QStringLiteral("org.kde.plasmashell"), + QStringLiteral("/org/kde/osdService"), + QStringLiteral("org.kde.osdService"), + QStringLiteral("mediaPlayerVolumeChanged") + ); + + msg.setArguments({ + qRound(data.value(QStringLiteral("Volume")).toDouble() * 100), + data.value("Identity", ""), + data.value("Desktop Icon Name", "") + }); + + QDBusConnection::sessionBus().asyncCall(msg); + } + }); } Plasma::ServiceJob* PlayerControl::createJob(const QString& operation,