| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | /*
 | 
					
						
							|  |  |  | 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"
 | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | #include "base/platform/linux/base_linux_glibmm_helper.h"
 | 
					
						
							|  |  |  | #include "base/platform/linux/base_linux_dbus_utilities.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | #include <glibmm.h>
 | 
					
						
							|  |  |  | #include <giomm.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-02 13:36:57 +04:00
										 |  |  | void KeyPressed( | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | 		const Glib::RefPtr<Gio::DBus::Connection> &connection, | 
					
						
							|  |  |  | 		const Glib::ustring &sender_name, | 
					
						
							|  |  |  | 		const Glib::ustring &object_path, | 
					
						
							|  |  |  | 		const Glib::ustring &interface_name, | 
					
						
							|  |  |  | 		const Glib::ustring &signal_name, | 
					
						
							|  |  |  | 		const Glib::VariantContainerBase ¶meters) { | 
					
						
							|  |  |  | 	try { | 
					
						
							|  |  |  | 		auto parametersCopy = parameters; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const auto app = base::Platform::GlibVariantCast<Glib::ustring>( | 
					
						
							|  |  |  | 			parametersCopy.get_child(0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const auto key = base::Platform::GlibVariantCast<Glib::ustring>( | 
					
						
							|  |  |  | 			parametersCopy.get_child(1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (app != QCoreApplication::applicationName().toStdString()) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | 		Core::Sandbox::Instance().customEnterFromEventLoop([&] { | 
					
						
							|  |  |  | 			if (key == "Play") { | 
					
						
							|  |  |  | 				Media::Player::instance()->playPause(); | 
					
						
							|  |  |  | 			} else if (key == "Stop") { | 
					
						
							|  |  |  | 				Media::Player::instance()->stop(); | 
					
						
							|  |  |  | 			} else if (key == "Next") { | 
					
						
							|  |  |  | 				Media::Player::instance()->next(); | 
					
						
							|  |  |  | 			} else if (key == "Previous") { | 
					
						
							|  |  |  | 				Media::Player::instance()->previous(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	} catch (...) { | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-02 13:36:57 +04:00
										 |  |  | } // namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class GSDMediaKeys::Private { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 	Glib::RefPtr<Gio::DBus::Connection> dbusConnection; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Glib::ustring service; | 
					
						
							|  |  |  | 	Glib::ustring objectPath; | 
					
						
							|  |  |  | 	Glib::ustring interface; | 
					
						
							|  |  |  | 	uint signalId = 0; | 
					
						
							|  |  |  | 	bool grabbed = false; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | GSDMediaKeys::GSDMediaKeys() | 
					
						
							|  |  |  | : _private(std::make_unique<Private>()) { | 
					
						
							|  |  |  | 	try { | 
					
						
							|  |  |  | 		_private->dbusConnection = Gio::DBus::Connection::get_sync( | 
					
						
							|  |  |  | 			Gio::DBus::BusType::BUS_TYPE_SESSION); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (base::Platform::DBus::NameHasOwner( | 
					
						
							|  |  |  | 			_private->dbusConnection, | 
					
						
							|  |  |  | 			std::string(kService))) { | 
					
						
							|  |  |  | 			_private->service = std::string(kService); | 
					
						
							|  |  |  | 			_private->objectPath = std::string(kObjectPath); | 
					
						
							|  |  |  | 			_private->interface = std::string(kInterface); | 
					
						
							|  |  |  | 		} else if (base::Platform::DBus::NameHasOwner( | 
					
						
							|  |  |  | 			_private->dbusConnection, | 
					
						
							|  |  |  | 			std::string(kOldService))) { | 
					
						
							|  |  |  | 			_private->service = std::string(kOldService); | 
					
						
							|  |  |  | 			_private->objectPath = std::string(kObjectPath); | 
					
						
							|  |  |  | 			_private->interface = std::string(kInterface); | 
					
						
							|  |  |  | 		} else if (base::Platform::DBus::NameHasOwner( | 
					
						
							|  |  |  | 			_private->dbusConnection, | 
					
						
							|  |  |  | 			std::string(kMATEService))) { | 
					
						
							|  |  |  | 			_private->service = std::string(kMATEService); | 
					
						
							|  |  |  | 			_private->objectPath = std::string(kMATEObjectPath); | 
					
						
							|  |  |  | 			_private->interface = std::string(kMATEInterface); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | 		_private->dbusConnection->call_sync( | 
					
						
							|  |  |  | 			_private->objectPath, | 
					
						
							|  |  |  | 			_private->interface, | 
					
						
							|  |  |  | 			"GrabMediaPlayerKeys", | 
					
						
							|  |  |  | 			base::Platform::MakeGlibVariant(std::tuple{ | 
					
						
							|  |  |  | 				Glib::ustring( | 
					
						
							|  |  |  | 					QCoreApplication::applicationName() | 
					
						
							|  |  |  | 						.toStdString()), | 
					
						
							|  |  |  | 				uint(0), | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 			_private->service); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_private->grabbed = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_private->signalId = _private->dbusConnection->signal_subscribe( | 
					
						
							| 
									
										
										
										
											2021-05-02 13:36:57 +04:00
										 |  |  | 			sigc::ptr_fun(KeyPressed), | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | 			_private->service, | 
					
						
							|  |  |  | 			_private->interface, | 
					
						
							|  |  |  | 			"MediaPlayerKeyPressed", | 
					
						
							|  |  |  | 			_private->objectPath); | 
					
						
							|  |  |  | 	} catch (...) { | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GSDMediaKeys::~GSDMediaKeys() { | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | 	if (_private->dbusConnection) { | 
					
						
							|  |  |  | 		if (_private->signalId != 0) { | 
					
						
							|  |  |  | 			_private->dbusConnection->signal_unsubscribe(_private->signalId); | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-28 06:34:41 +04:00
										 |  |  | 		if (_private->grabbed) { | 
					
						
							|  |  |  | 			try { | 
					
						
							|  |  |  | 				_private->dbusConnection->call_sync( | 
					
						
							|  |  |  | 					_private->objectPath, | 
					
						
							|  |  |  | 					_private->interface, | 
					
						
							|  |  |  | 					"ReleaseMediaPlayerKeys", | 
					
						
							|  |  |  | 					base::Platform::MakeGlibVariant(std::tuple{ | 
					
						
							|  |  |  | 						Glib::ustring( | 
					
						
							|  |  |  | 							QCoreApplication::applicationName() | 
					
						
							|  |  |  | 								.toStdString()) | 
					
						
							|  |  |  | 					}), | 
					
						
							|  |  |  | 					_private->service); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				_private->grabbed = false; | 
					
						
							|  |  |  | 			} catch (...) { | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-12-27 15:30:19 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace internal
 | 
					
						
							|  |  |  | } // namespace Platform
 |