2020-07-02 17:37:45 +00:00
|
|
|
#include <array>
|
2020-02-03 22:31:44 +00:00
|
|
|
#include <cstdio>
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
2020-07-02 17:37:45 +00:00
|
|
|
|
2020-12-04 05:59:20 +00:00
|
|
|
#include "dbus_helpers.h"
|
2020-02-03 22:31:44 +00:00
|
|
|
#include "dbus_info.h"
|
2020-04-13 00:02:52 +00:00
|
|
|
#include "string_utils.h"
|
2022-03-24 10:02:21 +00:00
|
|
|
#include "file_utils.h"
|
2020-02-03 22:31:44 +00:00
|
|
|
|
|
|
|
using ms = std::chrono::milliseconds;
|
2020-07-01 13:17:07 +00:00
|
|
|
using namespace DBus_helpers;
|
2020-07-02 17:37:45 +00:00
|
|
|
#define DBUS_TIMEOUT 2000 // ms
|
2020-02-03 22:31:44 +00:00
|
|
|
|
2020-07-01 02:28:02 +00:00
|
|
|
struct mutexed_metadata main_metadata;
|
2020-04-13 00:02:52 +00:00
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
namespace dbusmgr {
|
2020-06-30 14:24:49 +00:00
|
|
|
dbus_manager dbus_mgr;
|
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
template <class T>
|
|
|
|
static void assign_metadata_value(metadata& meta, const std::string& key,
|
|
|
|
const T& value) {
|
|
|
|
if (key == "PlaybackStatus") {
|
2020-07-01 02:28:02 +00:00
|
|
|
meta.playing = (value == "Playing");
|
2020-07-01 11:19:06 +00:00
|
|
|
meta.got_playback_data = true;
|
2020-07-02 17:37:45 +00:00
|
|
|
} else if (key == "xesam:title") {
|
2020-07-01 02:28:02 +00:00
|
|
|
meta.title = value;
|
2020-07-01 11:19:06 +00:00
|
|
|
meta.got_song_data = true;
|
2020-07-01 13:17:07 +00:00
|
|
|
meta.valid = true;
|
2020-07-02 17:37:45 +00:00
|
|
|
} else if (key == "xesam:artist") {
|
2020-07-01 11:19:06 +00:00
|
|
|
meta.artists = value;
|
|
|
|
meta.got_song_data = true;
|
2020-07-01 13:17:07 +00:00
|
|
|
meta.valid = true;
|
2020-07-02 17:37:45 +00:00
|
|
|
} else if (key == "xesam:album") {
|
2020-07-01 02:28:02 +00:00
|
|
|
meta.album = value;
|
2020-07-01 11:19:06 +00:00
|
|
|
meta.got_song_data = true;
|
2020-07-01 13:17:07 +00:00
|
|
|
meta.valid = true;
|
2020-07-02 17:37:45 +00:00
|
|
|
} else if (key == "mpris:artUrl") {
|
2020-07-01 02:28:02 +00:00
|
|
|
meta.artUrl = value;
|
2020-07-01 11:19:06 +00:00
|
|
|
meta.got_song_data = true;
|
2020-07-16 11:24:03 +00:00
|
|
|
} else if (key == "xesam:url") {
|
|
|
|
// HACK if there's no metadata then use this to clear old ones
|
|
|
|
meta.got_song_data = true;
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-03 10:43:59 +00:00
|
|
|
static std::string format_signal(const dbusmgr::DBusSignal& s) {
|
2020-07-01 02:28:02 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
ss << "type='signal',interface='" << s.intf << "'";
|
|
|
|
ss << ",member='" << s.signal << "'";
|
|
|
|
return ss.str();
|
|
|
|
}
|
2020-02-03 22:31:44 +00:00
|
|
|
|
2023-03-03 10:43:59 +00:00
|
|
|
static void parse_song_data(DBusMessageIter_wrap iter, metadata& meta){
|
2020-07-03 12:48:26 +00:00
|
|
|
iter.string_map_for_each([&meta](const std::string& key,
|
|
|
|
DBusMessageIter_wrap it) {
|
|
|
|
std::string val;
|
|
|
|
if (it.is_primitive()) {
|
|
|
|
val = it.get_stringified();
|
|
|
|
} else if (it.is_array()) {
|
|
|
|
it.array_for_each_stringify([&](const std::string& str) {
|
|
|
|
if (val.empty()) {
|
|
|
|
val = str;
|
|
|
|
} else {
|
|
|
|
val += ", " + str;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
assign_metadata_value(meta, key, val);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
static void parse_mpris_properties(libdbus_loader& dbus, DBusMessage* msg,
|
|
|
|
std::string& source, metadata& meta) {
|
2020-07-01 02:28:02 +00:00
|
|
|
/**
|
|
|
|
* Expected response Format:
|
|
|
|
* string,
|
|
|
|
* map{
|
|
|
|
* "Metadata" -> multimap,
|
|
|
|
* "PlaybackStatus" -> string
|
|
|
|
* }
|
2020-07-02 17:37:45 +00:00
|
|
|
*/
|
2020-02-03 22:31:44 +00:00
|
|
|
|
2020-07-01 02:28:02 +00:00
|
|
|
auto iter = DBusMessageIter_wrap(msg, &dbus);
|
|
|
|
source = iter.get_primitive<std::string>();
|
2020-07-02 17:37:45 +00:00
|
|
|
if (source != "org.mpris.MediaPlayer2.Player") return;
|
2020-02-03 22:31:44 +00:00
|
|
|
|
2020-07-01 02:28:02 +00:00
|
|
|
iter.next();
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!iter.is_array()) return;
|
2020-07-02 17:37:45 +00:00
|
|
|
|
2020-07-03 12:48:26 +00:00
|
|
|
iter.string_map_for_each([&meta](std::string& key, DBusMessageIter_wrap it) {
|
2020-07-02 17:37:45 +00:00
|
|
|
if (key == "Metadata") {
|
2020-07-03 12:48:26 +00:00
|
|
|
parse_song_data(it, meta);
|
2020-07-02 17:37:45 +00:00
|
|
|
} else if (key == "PlaybackStatus") {
|
2020-07-01 11:19:06 +00:00
|
|
|
auto val = it.get_stringified();
|
|
|
|
assign_metadata_value(meta, key, val);
|
2020-04-13 00:02:52 +00:00
|
|
|
}
|
2020-07-01 02:28:02 +00:00
|
|
|
});
|
|
|
|
meta.valid = (meta.artists.size() || !meta.title.empty());
|
|
|
|
}
|
2020-04-04 20:47:48 +00:00
|
|
|
|
2023-03-03 10:43:59 +00:00
|
|
|
static bool dbus_get_name_owner(dbusmgr::dbus_manager& dbus_mgr,
|
2020-07-02 17:37:45 +00:00
|
|
|
std::string& name_owner, const char* name) {
|
|
|
|
auto reply =
|
|
|
|
DBusMessage_wrap::new_method_call(
|
|
|
|
"org.freedesktop.DBus", "/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus", "GetNameOwner", &dbus_mgr.dbus())
|
|
|
|
.argument(name)
|
|
|
|
.send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!reply) return false;
|
2020-07-01 11:19:06 +00:00
|
|
|
|
|
|
|
auto iter = reply.iter();
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!iter.is_string()) return false;
|
2020-07-01 11:19:06 +00:00
|
|
|
name_owner = iter.get_primitive<std::string>();
|
2020-04-13 00:02:52 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-03-03 10:43:59 +00:00
|
|
|
static bool dbus_get_player_property(dbusmgr::dbus_manager& dbus_mgr, metadata& meta,
|
2020-07-02 17:37:45 +00:00
|
|
|
const char* dest, const char* prop) {
|
|
|
|
auto reply =
|
|
|
|
DBusMessage_wrap::new_method_call(dest, "/org/mpris/MediaPlayer2",
|
|
|
|
"org.freedesktop.DBus.Properties",
|
|
|
|
"Get", &dbus_mgr.dbus())
|
|
|
|
.argument("org.mpris.MediaPlayer2.Player")
|
|
|
|
.argument(prop)
|
|
|
|
.send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
|
2020-07-01 11:19:06 +00:00
|
|
|
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!reply) return false;
|
2020-07-01 11:19:06 +00:00
|
|
|
|
|
|
|
auto iter = reply.iter();
|
2020-07-03 12:48:26 +00:00
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
if (iter.is_array()) {
|
2020-07-03 12:48:26 +00:00
|
|
|
parse_song_data(iter, meta);
|
2020-07-02 17:37:45 +00:00
|
|
|
} else if (iter.is_primitive()) {
|
2020-07-01 02:28:02 +00:00
|
|
|
assign_metadata_value(meta, prop, iter.get_stringified());
|
2020-07-02 17:37:45 +00:00
|
|
|
} else {
|
2020-07-01 02:28:02 +00:00
|
|
|
return false;
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
2020-05-22 12:00:35 +00:00
|
|
|
return true;
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
|
2020-06-30 00:03:28 +00:00
|
|
|
namespace dbusmgr {
|
|
|
|
bool dbus_manager::get_media_player_metadata(metadata& meta, std::string name) {
|
2020-07-02 17:37:45 +00:00
|
|
|
if (name == "") name = m_active_player;
|
|
|
|
if (name == "") return false;
|
2020-07-31 20:05:50 +00:00
|
|
|
meta = {};
|
2020-07-01 02:28:02 +00:00
|
|
|
dbus_get_player_property(*this, meta, name.c_str(), "Metadata");
|
|
|
|
dbus_get_player_property(*this, meta, name.c_str(), "PlaybackStatus");
|
|
|
|
meta.valid = (meta.artists.size() || !meta.title.empty());
|
2020-05-22 12:00:35 +00:00
|
|
|
return true;
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
|
2021-08-21 15:12:12 +00:00
|
|
|
bool dbus_manager::init_internal() {
|
2020-05-22 12:00:35 +00:00
|
|
|
if (!m_dbus_ldr.IsLoaded() && !m_dbus_ldr.Load("libdbus-1.so.3")) {
|
2021-07-21 16:48:45 +00:00
|
|
|
SPDLOG_ERROR("Could not load libdbus-1.so.3");
|
2020-05-22 12:00:35 +00:00
|
|
|
return false;
|
|
|
|
}
|
2020-04-04 20:47:48 +00:00
|
|
|
|
|
|
|
m_dbus_ldr.error_init(&m_error);
|
2020-02-03 22:31:44 +00:00
|
|
|
|
2020-04-04 20:47:48 +00:00
|
|
|
m_dbus_ldr.threads_init_default();
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
if (nullptr ==
|
|
|
|
(m_dbus_conn = m_dbus_ldr.bus_get(DBUS_BUS_SESSION, &m_error))) {
|
2021-07-21 16:48:45 +00:00
|
|
|
SPDLOG_ERROR("{}", m_error.message);
|
2020-05-22 12:00:35 +00:00
|
|
|
m_dbus_ldr.error_free(&m_error);
|
|
|
|
return false;
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
2020-05-22 12:00:35 +00:00
|
|
|
|
2021-07-21 16:48:45 +00:00
|
|
|
SPDLOG_DEBUG("Connected to D-Bus as \"{}\"",
|
2021-07-16 00:28:46 +00:00
|
|
|
m_dbus_ldr.bus_get_unique_name(m_dbus_conn));
|
2020-02-03 22:31:44 +00:00
|
|
|
|
2021-09-08 20:35:09 +00:00
|
|
|
m_dbus_ldr.connection_add_filter(m_dbus_conn, filter_signals,
|
|
|
|
reinterpret_cast<void*>(this), nullptr);
|
|
|
|
|
|
|
|
start_thread();
|
|
|
|
|
2020-06-30 00:03:28 +00:00
|
|
|
dbus_list_name_to_owner();
|
2020-02-03 22:31:44 +00:00
|
|
|
m_inited = true;
|
2020-05-22 12:00:35 +00:00
|
|
|
return true;
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
|
2021-08-21 15:12:12 +00:00
|
|
|
bool dbus_manager::init(Service srv) {
|
|
|
|
if (!m_inited && !init_internal())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
connect_to_signals(srv);
|
|
|
|
m_active_srvs |= srv;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool dbus_manager::init_mpris(const std::string& requested_player) {
|
|
|
|
if (!requested_player.empty()) {
|
|
|
|
m_requested_player = "org.mpris.MediaPlayer2." + requested_player;
|
|
|
|
} else
|
|
|
|
m_requested_player.clear();
|
|
|
|
|
|
|
|
if (m_active_srvs & SRV_MPRIS) {
|
|
|
|
select_active_player();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
SPDLOG_WARN("D-Bus hasn't been inited yet.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
bool dbus_manager::select_active_player() {
|
|
|
|
auto old_active_player = m_active_player;
|
|
|
|
m_active_player = "";
|
2020-07-03 12:48:26 +00:00
|
|
|
metadata meta {};
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!m_requested_player.empty()) {
|
2020-07-02 18:09:17 +00:00
|
|
|
// If the requested player is available, use it
|
|
|
|
if (m_name_owners.count(m_requested_player) > 0) {
|
|
|
|
m_active_player = m_requested_player;
|
2021-07-21 16:48:45 +00:00
|
|
|
SPDLOG_DEBUG("Selecting requested player: {}", m_requested_player);
|
2020-07-02 18:09:17 +00:00
|
|
|
get_media_player_metadata(meta, m_active_player);
|
|
|
|
}
|
2020-07-03 12:48:26 +00:00
|
|
|
} else {
|
2020-07-02 18:09:17 +00:00
|
|
|
// If no player is requested, use any player that is currently playing
|
|
|
|
if (m_active_player.empty()) {
|
2020-07-03 12:48:26 +00:00
|
|
|
auto it = std::find_if(m_name_owners.begin(), m_name_owners.end(), [this, &meta](auto& entry){
|
|
|
|
auto& name = entry.first;
|
2020-11-09 18:11:16 +00:00
|
|
|
this->get_media_player_metadata(meta, name);
|
2020-07-03 12:48:26 +00:00
|
|
|
if(meta.playing) {
|
|
|
|
return true;
|
2020-07-02 18:09:17 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
meta = {};
|
2020-07-03 12:48:26 +00:00
|
|
|
return false;
|
2020-07-02 18:09:17 +00:00
|
|
|
}
|
2020-07-03 12:48:26 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
if(it != m_name_owners.end()){
|
|
|
|
m_active_player = it->first;
|
2021-07-21 16:48:45 +00:00
|
|
|
SPDLOG_DEBUG("Selecting fallback player: {}", m_active_player);
|
2020-07-02 17:37:45 +00:00
|
|
|
}
|
2020-06-30 00:03:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!m_active_player.empty()) {
|
2020-07-16 11:22:00 +00:00
|
|
|
onNewPlayer(meta);
|
2020-07-02 17:37:45 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
2021-07-21 16:48:45 +00:00
|
|
|
SPDLOG_DEBUG("No active players");
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!old_active_player.empty()) {
|
2020-07-02 17:37:45 +00:00
|
|
|
onNoPlayer();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2020-06-30 00:03:28 +00:00
|
|
|
}
|
|
|
|
|
2021-08-21 15:12:12 +00:00
|
|
|
void dbus_manager::deinit(Service srv) {
|
2020-07-02 17:37:45 +00:00
|
|
|
if (!m_inited) return;
|
2020-04-10 19:33:27 +00:00
|
|
|
|
2021-08-21 15:12:12 +00:00
|
|
|
m_active_srvs &= ~srv;
|
|
|
|
if (m_dbus_conn)
|
|
|
|
disconnect_from_signals(srv);
|
|
|
|
|
2020-04-10 19:33:27 +00:00
|
|
|
// unreference system bus connection instead of closing it
|
2021-08-21 15:12:12 +00:00
|
|
|
if (m_dbus_conn && !m_active_srvs) {
|
2021-09-08 20:35:09 +00:00
|
|
|
m_dbus_ldr.connection_remove_filter(m_dbus_conn, filter_signals,
|
|
|
|
reinterpret_cast<void*>(this));
|
|
|
|
stop_thread();
|
2020-04-10 19:33:27 +00:00
|
|
|
m_dbus_ldr.connection_unref(m_dbus_conn);
|
|
|
|
m_dbus_conn = nullptr;
|
2021-08-21 15:12:12 +00:00
|
|
|
m_dbus_ldr.error_free(&m_error);
|
|
|
|
m_inited = false;
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
2020-04-10 19:33:27 +00:00
|
|
|
}
|
|
|
|
|
2022-04-01 21:35:48 +00:00
|
|
|
dbus_manager::~dbus_manager() { deinit(static_cast<Service>(m_active_srvs)); }
|
2020-02-03 22:31:44 +00:00
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
DBusHandlerResult dbus_manager::filter_signals(DBusConnection* conn,
|
|
|
|
DBusMessage* msg,
|
|
|
|
void* userData) {
|
2020-06-30 14:24:49 +00:00
|
|
|
auto& manager = *reinterpret_cast<dbus_manager*>(userData);
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
for (auto& sig : manager.m_signals) {
|
|
|
|
if (manager.m_dbus_ldr.message_is_signal(msg, sig.intf, sig.signal)) {
|
2020-06-30 14:24:49 +00:00
|
|
|
auto sender = manager.m_dbus_ldr.message_get_sender(msg);
|
2020-07-02 17:37:45 +00:00
|
|
|
if ((manager.*(sig.handler))(msg, sender))
|
2020-06-30 14:24:49 +00:00
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
|
|
else
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
bool dbus_manager::handle_properties_changed(DBusMessage* msg,
|
|
|
|
const char* sender) {
|
2020-06-30 14:24:49 +00:00
|
|
|
std::string source;
|
|
|
|
|
2020-07-01 02:28:02 +00:00
|
|
|
metadata meta;
|
|
|
|
parse_mpris_properties(m_dbus_ldr, msg, source, meta);
|
2020-06-30 14:24:49 +00:00
|
|
|
#ifndef NDEBUG
|
2020-07-01 02:28:02 +00:00
|
|
|
std::cerr << "PropertiesChanged Signal received:\n";
|
|
|
|
std::cerr << "\tSource: " << source << "\n";
|
|
|
|
std::cerr << "active_player: " << m_active_player << "\n";
|
2020-07-02 17:37:45 +00:00
|
|
|
std::cerr << "active_player's owner: " << m_name_owners[m_active_player]
|
|
|
|
<< "\n";
|
2020-07-01 02:28:02 +00:00
|
|
|
std::cerr << "sender: " << sender << "\n";
|
2020-06-30 14:24:49 +00:00
|
|
|
#endif
|
2020-07-02 17:37:45 +00:00
|
|
|
if (source != "org.mpris.MediaPlayer2.Player") return false;
|
2020-06-30 14:24:49 +00:00
|
|
|
|
2020-12-04 05:59:20 +00:00
|
|
|
if (m_active_player == "" ||
|
|
|
|
(m_requested_player.empty() && !main_metadata.meta.playing)) {
|
2020-07-02 17:37:45 +00:00
|
|
|
select_active_player();
|
2020-07-03 12:48:26 +00:00
|
|
|
}
|
|
|
|
else if (m_name_owners[m_active_player] == sender) {
|
2020-07-02 17:37:45 +00:00
|
|
|
onPlayerUpdate(meta);
|
2020-06-30 14:24:49 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
bool dbus_manager::handle_name_owner_changed(DBusMessage* _msg,
|
|
|
|
const char* sender) {
|
2020-06-30 14:24:49 +00:00
|
|
|
std::vector<std::string> str;
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
for (auto iter = DBusMessageIter_wrap(_msg, &m_dbus_ldr); iter;
|
|
|
|
iter.next()) {
|
|
|
|
str.push_back(iter.get_primitive<std::string>());
|
2020-06-30 14:24:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// register new name
|
2020-07-02 17:37:45 +00:00
|
|
|
if (str.size() == 3 && starts_with(str[0], "org.mpris.MediaPlayer2.") &&
|
|
|
|
!str[2].empty()) {
|
2020-06-30 14:24:49 +00:00
|
|
|
m_name_owners[str[0]] = str[2];
|
2020-07-02 17:37:45 +00:00
|
|
|
if (str[0] == m_requested_player) {
|
|
|
|
select_active_player();
|
2020-06-30 14:24:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// did a player quit?
|
|
|
|
if (str[2].empty()) {
|
2020-07-02 17:37:45 +00:00
|
|
|
if (str.size() == 3 && str[0] == m_active_player) {
|
2020-06-30 14:24:49 +00:00
|
|
|
m_name_owners.erase(str[0]);
|
|
|
|
select_active_player();
|
2020-07-01 02:28:02 +00:00
|
|
|
}
|
2020-06-30 14:24:49 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-03-24 10:02:21 +00:00
|
|
|
bool dbus_manager::gamemode_enabled(pid_t pid) {
|
2021-08-21 15:12:12 +00:00
|
|
|
if (!m_inited)
|
|
|
|
return false;
|
|
|
|
|
2022-03-24 10:02:21 +00:00
|
|
|
static int isvc = file_exists("/.flatpak-info") ? 1 : 0;
|
|
|
|
const struct dbus_ep
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
const char *path;
|
|
|
|
const char *iface;
|
|
|
|
} svc[] {
|
|
|
|
{
|
|
|
|
"com.feralinteractive.GameMode",
|
|
|
|
"/com/feralinteractive/GameMode",
|
|
|
|
"com.feralinteractive.GameMode"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"org.freedesktop.portal.Desktop",
|
|
|
|
"/org/freedesktop/portal/desktop",
|
|
|
|
"org.freedesktop.portal.GameMode"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-08-21 15:12:12 +00:00
|
|
|
auto reply =
|
|
|
|
DBusMessage_wrap::new_method_call(
|
2022-03-24 10:02:21 +00:00
|
|
|
svc[isvc].name, svc[isvc].path, svc[isvc].iface,
|
|
|
|
"QueryStatus", &dbus_mgr.dbus())
|
2021-08-21 15:12:12 +00:00
|
|
|
.argument(pid)
|
|
|
|
.send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
|
|
|
|
if (!reply) return false;
|
|
|
|
|
|
|
|
auto iter = reply.iter();
|
|
|
|
if (!iter.is_signed()) return false;
|
|
|
|
return !!iter.get_primitive<int32_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool dbus_manager::handle_game_registered(DBusMessage* _msg,
|
|
|
|
const char* sender) {
|
|
|
|
auto iter = DBusMessageIter_wrap(_msg, &m_dbus_ldr);
|
|
|
|
auto pid = iter.get_primitive<int32_t>();
|
|
|
|
iter.next();
|
|
|
|
auto path = iter.get_primitive<std::string>();
|
|
|
|
SPDLOG_INFO("Game registered: {} '{}'", pid, path);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool dbus_manager::handle_game_unregistered(DBusMessage* _msg,
|
|
|
|
const char* sender) {
|
|
|
|
auto iter = DBusMessageIter_wrap(_msg, &m_dbus_ldr);
|
|
|
|
auto pid = iter.get_primitive<int32_t>();
|
|
|
|
iter.next();
|
|
|
|
auto path = iter.get_primitive<std::string>();
|
|
|
|
SPDLOG_INFO("Game unregistered: {} '{}'", pid, path);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dbus_manager::connect_to_signals(Service srv) {
|
2020-02-03 22:31:44 +00:00
|
|
|
for (auto kv : m_signals) {
|
2021-08-21 15:12:12 +00:00
|
|
|
if (!(kv.srv & srv)) continue;
|
2020-02-03 22:31:44 +00:00
|
|
|
auto signal = format_signal(kv);
|
2020-04-04 20:47:48 +00:00
|
|
|
m_dbus_ldr.bus_add_match(m_dbus_conn, signal.c_str(), &m_error);
|
|
|
|
if (m_dbus_ldr.error_is_set(&m_error)) {
|
2021-07-21 16:48:45 +00:00
|
|
|
SPDLOG_ERROR("{}: {}", m_error.name, m_error.message);
|
2020-04-04 20:47:48 +00:00
|
|
|
m_dbus_ldr.error_free(&m_error);
|
2020-07-02 17:37:45 +00:00
|
|
|
// return;
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-21 15:12:12 +00:00
|
|
|
void dbus_manager::disconnect_from_signals(Service srv) {
|
2020-02-03 22:31:44 +00:00
|
|
|
for (auto kv : m_signals) {
|
2021-08-21 15:12:12 +00:00
|
|
|
if (!(kv.srv & srv)) continue;
|
2020-02-03 22:31:44 +00:00
|
|
|
auto signal = format_signal(kv);
|
2020-04-04 20:47:48 +00:00
|
|
|
m_dbus_ldr.bus_remove_match(m_dbus_conn, signal.c_str(), &m_error);
|
|
|
|
if (m_dbus_ldr.error_is_set(&m_error)) {
|
2022-04-01 21:35:48 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
// spdlog might be destroyed by now
|
|
|
|
std::cerr << "[MANGOHUD] [debug] " << __func__ << " "
|
|
|
|
<< m_error.name << ": " << m_error.message << std::endl;
|
|
|
|
#endif
|
2020-04-04 20:47:48 +00:00
|
|
|
m_dbus_ldr.error_free(&m_error);
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
bool dbus_manager::dbus_list_name_to_owner() {
|
|
|
|
auto reply =
|
|
|
|
DBusMessage_wrap::new_method_call(
|
|
|
|
"org.freedesktop.DBus", "/org/freedesktop/DBus",
|
|
|
|
"org.freedesktop.DBus", "ListNames", &dbus_mgr.dbus())
|
|
|
|
.send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!reply) return false;
|
2020-06-30 00:03:28 +00:00
|
|
|
|
2020-07-01 13:17:07 +00:00
|
|
|
auto iter = reply.iter();
|
2020-06-30 00:03:28 +00:00
|
|
|
|
2020-12-04 05:59:20 +00:00
|
|
|
if (!iter.is_array()) {
|
2020-07-01 11:19:06 +00:00
|
|
|
return false;
|
|
|
|
}
|
2020-07-02 17:37:45 +00:00
|
|
|
iter.array_for_each_value<std::string>([&](std::string name) {
|
2021-07-30 16:11:13 +00:00
|
|
|
if (!starts_with(name, "org.mpris.MediaPlayer2.")) return;
|
2020-07-01 13:17:07 +00:00
|
|
|
std::string owner;
|
2020-07-02 17:37:45 +00:00
|
|
|
if (dbus_get_name_owner(dbus_mgr, owner, name.c_str())) {
|
2020-06-30 00:03:28 +00:00
|
|
|
m_name_owners[name] = owner;
|
|
|
|
}
|
2020-07-01 02:28:02 +00:00
|
|
|
});
|
2020-06-30 00:03:28 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
void dbus_manager::stop_thread() {
|
2020-02-03 22:31:44 +00:00
|
|
|
m_quit = true;
|
2020-07-02 17:37:45 +00:00
|
|
|
if (m_thread.joinable()) m_thread.join();
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
void dbus_manager::start_thread() {
|
2020-02-03 22:31:44 +00:00
|
|
|
stop_thread();
|
|
|
|
m_quit = false;
|
2020-06-30 00:03:28 +00:00
|
|
|
m_thread = std::thread(&dbus_manager::dbus_thread, this);
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
void dbus_manager::dbus_thread() {
|
2020-06-30 14:24:49 +00:00
|
|
|
using namespace std::chrono_literals;
|
2020-07-02 17:37:45 +00:00
|
|
|
while (!m_quit && m_dbus_ldr.connection_read_write_dispatch(m_dbus_conn, 0))
|
2020-06-30 14:24:49 +00:00
|
|
|
std::this_thread::sleep_for(10ms);
|
2020-02-03 22:31:44 +00:00
|
|
|
}
|
|
|
|
|
2020-07-02 17:37:45 +00:00
|
|
|
void dbus_manager::onNoPlayer() {
|
|
|
|
std::lock_guard<std::mutex> lck(main_metadata.mtx);
|
|
|
|
main_metadata.meta = {};
|
|
|
|
main_metadata.ticker = {};
|
2020-05-10 12:11:56 +00:00
|
|
|
}
|
2020-07-02 17:37:45 +00:00
|
|
|
|
|
|
|
void dbus_manager::onNewPlayer(metadata& meta) {
|
|
|
|
std::lock_guard<std::mutex> lck(main_metadata.mtx);
|
|
|
|
main_metadata.meta = meta;
|
|
|
|
main_metadata.ticker = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
void dbus_manager::onPlayerUpdate(metadata& meta) {
|
|
|
|
std::lock_guard<std::mutex> lck(main_metadata.mtx);
|
|
|
|
if (meta.got_song_data) {
|
|
|
|
// If the song has changed, reset the ticker
|
|
|
|
if (main_metadata.meta.artists != meta.artists ||
|
|
|
|
main_metadata.meta.album != meta.album ||
|
|
|
|
main_metadata.meta.title != meta.title) {
|
|
|
|
main_metadata.ticker = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
main_metadata.meta = meta;
|
|
|
|
main_metadata.meta.playing = true;
|
|
|
|
}
|
|
|
|
if (meta.got_playback_data) {
|
|
|
|
main_metadata.meta.playing = meta.playing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace dbusmgr
|