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)
{