tdesktop/Telegram/SourceFiles/platform/linux/linux_gsd_media_keys.cpp

182 lines
4.2 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/linux/linux_gsd_media_keys.h"
#include "core/sandbox.h"
#include "media/player/media_player_instance.h"
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusConnectionInterface>
extern "C" {
#undef signals
#include <gio/gio.h>
#define signals public
} // extern "C"
namespace Platform {
namespace internal {
namespace {
constexpr auto kService = "org.gnome.SettingsDaemon.MediaKeys"_cs;
constexpr auto kOldService = "org.gnome.SettingsDaemon"_cs;
constexpr auto kMATEService = "org.mate.SettingsDaemon"_cs;
constexpr auto kObjectPath = "/org/gnome/SettingsDaemon/MediaKeys"_cs;
constexpr auto kMATEObjectPath = "/org/mate/SettingsDaemon/MediaKeys"_cs;
constexpr auto kInterface = kService;
constexpr auto kMATEInterface = "org.mate.SettingsDaemon.MediaKeys"_cs;
void KeyPressed(
GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data) {
gchar *appUtf8;
gchar *keyUtf8;
g_variant_get(parameters, "(ss)", &appUtf8, &keyUtf8);
const auto app = QString::fromUtf8(appUtf8);
const auto key = QString::fromUtf8(keyUtf8);
g_free(keyUtf8);
g_free(appUtf8);
if (app != QCoreApplication::applicationName()) {
return;
}
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
if (key == qstr("Play")) {
Media::Player::instance()->playPause();
} else if (key == qstr("Stop")) {
Media::Player::instance()->stop();
} else if (key == qstr("Next")) {
Media::Player::instance()->next();
} else if (key == qstr("Previous")) {
Media::Player::instance()->previous();
}
});
}
} // namespace
GSDMediaKeys::GSDMediaKeys() {
GError *error = nullptr;
const auto interface = QDBusConnection::sessionBus().interface();
if (!interface) {
return;
}
if (interface->isServiceRegistered(kService.utf16())) {
_service = kService.utf16();
_objectPath = kObjectPath.utf16();
_interface = kInterface.utf16();
} else if (interface->isServiceRegistered(kOldService.utf16())) {
_service = kOldService.utf16();
_objectPath = kObjectPath.utf16();
_interface = kInterface.utf16();
} else if (interface->isServiceRegistered(kMATEService.utf16())) {
_service = kMATEService.utf16();
_objectPath = kMATEObjectPath.utf16();
_interface = kMATEInterface.utf16();
} else {
return;
}
_dbusConnection = g_bus_get_sync(
G_BUS_TYPE_SESSION,
nullptr,
&error);
if (error) {
LOG(("GSD Media Keys Error: %1").arg(error->message));
g_error_free(error);
return;
}
auto reply = g_dbus_connection_call_sync(
_dbusConnection,
_service.toUtf8(),
_objectPath.toUtf8(),
_interface.toUtf8(),
"GrabMediaPlayerKeys",
g_variant_new(
"(su)",
QCoreApplication::applicationName().toUtf8().constData(),
0),
nullptr,
G_DBUS_CALL_FLAGS_NONE,
-1,
nullptr,
&error);
if (!error) {
_grabbed = true;
g_variant_unref(reply);
} else {
LOG(("GSD Media Keys Error: %1").arg(error->message));
g_error_free(error);
}
_signalId = g_dbus_connection_signal_subscribe(
_dbusConnection,
_service.toUtf8(),
_interface.toUtf8(),
"MediaPlayerKeyPressed",
_objectPath.toUtf8(),
nullptr,
G_DBUS_SIGNAL_FLAGS_NONE,
KeyPressed,
nullptr,
nullptr);
}
GSDMediaKeys::~GSDMediaKeys() {
GError *error = nullptr;
if (_signalId != 0) {
g_dbus_connection_signal_unsubscribe(
_dbusConnection,
_signalId);
}
if (_grabbed) {
auto reply = g_dbus_connection_call_sync(
_dbusConnection,
_service.toUtf8(),
_objectPath.toUtf8(),
_interface.toUtf8(),
"ReleaseMediaPlayerKeys",
g_variant_new(
"(s)",
QCoreApplication::applicationName().toUtf8().constData()),
nullptr,
G_DBUS_CALL_FLAGS_NONE,
-1,
nullptr,
&error);
if (!error) {
_grabbed = false;
g_variant_unref(reply);
} else {
LOG(("GSD Media Keys Error: %1").arg(error->message));
g_error_free(error);
}
}
if (_dbusConnection) {
g_object_unref(_dbusConnection);
}
}
} // namespace internal
} // namespace Platform