diff --git a/applets/mediacontroller/contents/ui/main.qml b/applets/mediacontroller/contents/ui/main.qml --- a/applets/mediacontroller/contents/ui/main.qml +++ b/applets/mediacontroller/contents/ui/main.qml @@ -155,6 +155,15 @@ anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.BackButton | Qt.ForwardButton + + onWheel: { + var service = mpris2Source.serviceForSource(mpris2Source.current) + var operation = service.operationDescription("ChangeVolume") + operation.delta = (wheel.angleDelta.y / 120) * 0.03 + operation.showOSD = true + service.startOperationCall(operation) + } + onClicked: { switch (mouse.button) { case Qt.MiddleButton: diff --git a/dataengines/mpris2/mpris2.operations b/dataengines/mpris2/mpris2.operations --- a/dataengines/mpris2/mpris2.operations +++ b/dataengines/mpris2/mpris2.operations @@ -47,4 +47,12 @@ + + + + + + + + diff --git a/dataengines/mpris2/multiplexedservice.cpp b/dataengines/mpris2/multiplexedservice.cpp --- a/dataengines/mpris2/multiplexedservice.cpp +++ b/dataengines/mpris2/multiplexedservice.cpp @@ -146,5 +146,27 @@ } } ); + + QAction *volumeupAction = m_actionCollection->addAction(QStringLiteral("mediavolumeup")); + volumeupAction->setText(i18n("Media volume up")); + KGlobalAccel::setGlobalShortcut(volumeupAction, QKeySequence()); + connect(volumeupAction, &QAction::triggered, this, + [this] { + if (m_control && m_control->playerInterface()->canControl()) { + m_control->changeVolume(0.05, true); + } + } + ); + + QAction *volumedownAction = m_actionCollection->addAction(QStringLiteral("mediavolumedown")); + volumedownAction->setText(i18n("Media volume down")); + KGlobalAccel::setGlobalShortcut(volumedownAction, QKeySequence()); + connect(volumedownAction, &QAction::triggered, this, + [this] { + if (m_control && m_control->playerInterface()->canControl()) { + m_control->changeVolume(-0.05, true); + } + } + ); } diff --git a/dataengines/mpris2/playeractionjob.cpp b/dataengines/mpris2/playeractionjob.cpp --- a/dataengines/mpris2/playeractionjob.cpp +++ b/dataengines/mpris2/playeractionjob.cpp @@ -131,6 +131,26 @@ setError(MissingArgument); emitResult(); } + } else if (operation == QLatin1String("ChangeVolume")) { + if (parameters().value(QStringLiteral("delta")).type() != QVariant::Double) { + setErrorText(QStringLiteral("delta")); + setError(MissingArgument); + emitResult(); + return; + } + if (parameters().value(QStringLiteral("showOSD")).type() != QVariant::Bool) { + setErrorText(QStringLiteral("showOSD")); + setError(MissingArgument); + emitResult(); + return; + } + + m_controller->changeVolume( + parameters()[QStringLiteral("delta")].toDouble(), + parameters()[QStringLiteral("showOSD")].toBool() + ); + setError(NoError); + emitResult(); } else if (operation == QLatin1String("GetPosition")) { m_controller->updatePosition(); } else { diff --git a/dataengines/mpris2/playercontrol.h b/dataengines/mpris2/playercontrol.h --- a/dataengines/mpris2/playercontrol.h +++ b/dataengines/mpris2/playercontrol.h @@ -49,6 +49,8 @@ Plasma::ServiceJob* createJob(const QString& operation, QMap& parameters) override; + void changeVolume(double delta, bool showOSD); + Q_SIGNALS: void enabledOperationsChanged(); diff --git a/dataengines/mpris2/playercontrol.cpp b/dataengines/mpris2/playercontrol.cpp --- a/dataengines/mpris2/playercontrol.cpp +++ b/dataengines/mpris2/playercontrol.cpp @@ -63,6 +63,7 @@ setOperationEnabled(QStringLiteral("SetPosition"), caps & PlayerContainer::CanSeek); setOperationEnabled(QStringLiteral("OpenUri"), caps & PlayerContainer::CanControl); setOperationEnabled(QStringLiteral("SetVolume"), caps & PlayerContainer::CanControl); + setOperationEnabled(QStringLiteral("ChangeVolume"), caps & PlayerContainer::CanControl); setOperationEnabled(QStringLiteral("SetLoopStatus"), caps & PlayerContainer::CanControl); setOperationEnabled(QStringLiteral("SetRate"), caps & PlayerContainer::CanControl); setOperationEnabled(QStringLiteral("SetShuffle"), caps & PlayerContainer::CanControl); @@ -89,6 +90,31 @@ 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") + ); + + msg.setArguments({ + (int)(100 * newVolume), + data.value("Identity", ""), + data.value("Desktop Icon Name", "") + }); + + QDBusConnection::sessionBus().asyncCall(msg); + } +} + Plasma::ServiceJob* PlayerControl::createJob(const QString& operation, QMap& parameters) {