diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -118,6 +118,7 @@
waylandserver.cpp
powermanagement.cpp
powermanagement_inhibition.cpp
+ mpris.cpp
)
qt5_add_dbus_adaptor(ksld_SRCS ${screensaver_dbusXML} interface.h ScreenLocker::Interface)
qt5_add_dbus_adaptor(ksld_SRCS ${kscreensaver_dbusXML} interface.h ScreenLocker::Interface kscreensaveradaptor KScreenSaverAdaptor)
diff --git a/kcfg/kscreenlockersettings.kcfg b/kcfg/kscreenlockersettings.kcfg
--- a/kcfg/kscreenlockersettings.kcfg
+++ b/kcfg/kscreenlockersettings.kcfg
@@ -31,6 +31,10 @@
true
+
+
+ false
+
diff --git a/kcm/kcm.ui b/kcm/kcm.ui
--- a/kcm/kcm.ui
+++ b/kcm/kcm.ui
@@ -132,6 +132,20 @@
+ -
+
+
+ Pause media players when locked:
+
+
+
+ -
+
+
+
+
+
+
diff --git a/ksldapp.h b/ksldapp.h
--- a/ksldapp.h
+++ b/ksldapp.h
@@ -34,6 +34,7 @@
class QTimer;
class KSldTest;
class PowerManagementInhibition;
+class MPris;
namespace KWayland
{
@@ -185,6 +186,7 @@
int m_greeterCrashedCounter = 0;
QProcessEnvironment m_greeterEnv;
PowerManagementInhibition *m_powerManagementInhibition;
+ MPris *m_mpris;
// for auto tests
friend KSldTest;
diff --git a/ksldapp.cpp b/ksldapp.cpp
--- a/ksldapp.cpp
+++ b/ksldapp.cpp
@@ -28,6 +28,7 @@
#include "logind.h"
#include "kscreensaversettings.h"
#include "powermanagement_inhibition.h"
+#include "mpris.h"
#include
#include
#include "waylandserver.h"
@@ -93,6 +94,7 @@
, m_logind(nullptr)
, m_greeterEnv(QProcessEnvironment::systemEnvironment())
, m_powerManagementInhibition(new PowerManagementInhibition(this))
+ , m_mpris(new MPris(this))
{
m_isX11 = QX11Info::isPlatformX11();
m_isWayland = QCoreApplication::instance()->property("platformName").toString().startsWith( QLatin1String("wayland"), Qt::CaseInsensitive);
@@ -500,6 +502,11 @@
void KSldApp::doUnlock()
{
qDebug() << "Grab Released";
+
+ if (KScreenSaverSettings::pauseMediaPlayers()) {
+ m_mpris->unpausePlayers();
+ }
+
if (m_isX11) {
xcb_connection_t *c = QX11Info::connection();
xcb_ungrab_keyboard(c, XCB_CURRENT_TIME);
@@ -631,6 +638,10 @@
if (m_isX11) {
XSync(QX11Info::display(), False);
}
+
+ if (KScreenSaverSettings::pauseMediaPlayers()) {
+ m_mpris->pausePlayers();
+ }
}
void KSldApp::hideLockWindow()
diff --git a/mpris.h b/mpris.h
new file mode 100644
--- /dev/null
+++ b/mpris.h
@@ -0,0 +1,43 @@
+/********************************************************************
+ KSld - the KDE Screenlocker Daemon
+ This file is part of the KDE project.
+
+ Copyright (C) 2016 Kai Uwe Broulik
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+
+#pragma once
+
+#include
+
+#include
+
+class MPris : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit MPris(QObject *parent = nullptr);
+ ~MPris() override;
+
+ void pausePlayers();
+ void unpausePlayers();
+
+private:
+ void isMediaPlayerPlaying(const QString &serviceName, std::function cb);
+
+ QStringList m_players;
+
+};
diff --git a/mpris.cpp b/mpris.cpp
new file mode 100644
--- /dev/null
+++ b/mpris.cpp
@@ -0,0 +1,129 @@
+/********************************************************************
+ KSld - the KDE Screenlocker Daemon
+ This file is part of the KDE project.
+
+ Copyright (C) 2016 Kai Uwe Broulik
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+
+#include "mpris.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+static const QString s_mprisPrefix = QStringLiteral("org.mpris.MediaPlayer2.");
+//static const QString s_solidPath = QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent");
+
+MPris::MPris(QObject *parent)
+ : QObject(parent)
+{
+ qDebug() << "HUI";
+}
+
+MPris::~MPris() = default;
+
+void MPris::pausePlayers()
+{
+ qDebug() << "Pause players";
+ QDBusPendingCall listNamesCall = QDBusConnection::sessionBus().interface()->asyncCall(QStringLiteral("ListNames"));
+ QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(listNamesCall, this);
+ connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
+ QDBusPendingReply reply = *watcher;
+ watcher->deleteLater();
+
+ if (reply.isError()) {
+ qWarning() << "Failed to fetch list of dbus service names";
+ return;
+ }
+
+ const QStringList &services = reply.value();
+ for (const QString &serviceName : services) {
+ if (!serviceName.startsWith(s_mprisPrefix)) {
+ continue;
+ }
+
+ qDebug() << "Check playback status for" << serviceName;
+
+ isMediaPlayerPlaying(serviceName, [this, serviceName](bool playing) {
+ if (playing) {
+ qDebug() << "PLAYER" << serviceName << "IS PLAYING";
+
+ QDBusMessage pauseMsg = QDBusMessage::createMethodCall(serviceName,
+ QStringLiteral("/org/mpris/MediaPlayer2"),
+ QStringLiteral("org.mpris.MediaPlayer2.Player"),
+ QStringLiteral("Pause"));
+ QDBusPendingReply pauseReply = QDBusConnection::sessionBus().asyncCall(pauseMsg);
+ QDBusPendingCallWatcher *pauseWatcher = new QDBusPendingCallWatcher(pauseReply, this);
+ QObject::connect(pauseWatcher, &QDBusPendingCallWatcher::finished, this, [this, serviceName](QDBusPendingCallWatcher *watcher) {
+ if (!watcher->isError()) {
+ m_players.append(serviceName);
+ }
+ watcher->deleteLater();
+ });
+ }
+ });
+ }
+ });
+}
+
+void MPris::unpausePlayers()
+{
+ qDebug() << "UNPAUSE PLAYERS";
+ for (const QString &serviceName : qAsConst(m_players)) {
+ qDebug() << "unpause" << serviceName;
+ QDBusConnection::sessionBus().asyncCall(
+ QDBusMessage::createMethodCall(serviceName,
+ QStringLiteral("/org/mpris/MediaPlayer2"),
+ QStringLiteral("org.mpris.MediaPlayer2.Player"),
+ QStringLiteral("Play"))
+ );
+ }
+ m_players.clear();
+}
+
+void MPris::isMediaPlayerPlaying(const QString &serviceName, std::function cb)
+{
+ QDBusMessage msg = QDBusMessage::createMethodCall(serviceName,
+ QStringLiteral("/org/mpris/MediaPlayer2"),
+ QStringLiteral("org.freedesktop.DBus.Properties"),
+ QStringLiteral("Get"));
+ msg.setArguments({
+ QStringLiteral("org.mpris.MediaPlayer2.Player"),
+ QStringLiteral("PlaybackStatus")
+ });
+
+ QDBusPendingReply reply = QDBusConnection::sessionBus().asyncCall(msg);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, cb](QDBusPendingCallWatcher *watcher) {
+ QDBusPendingReply reply = *watcher;
+ watcher->deleteLater();
+
+ if (reply.isError()) {
+ qWarning() << "Failed to check playback status";
+ return;
+ }
+
+ const QString &playbackStatus = reply.value().variant().toString();
+
+ cb(playbackStatus == QLatin1String("Playing"));
+ });
+}