Move interactions with main_metadata into separate functions

More tidying up of the helper classes
pull/264/head
Lars Krämer 4 years ago
parent 7cc76142f1
commit 9a34b55498

@ -1,59 +1,55 @@
#include <array>
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <array>
#include "dbus_helpers.hpp"
#include "dbus_info.h" #include "dbus_info.h"
#include "string_utils.h" #include "string_utils.h"
#include "dbus_helpers.hpp"
using ms = std::chrono::milliseconds; using ms = std::chrono::milliseconds;
using namespace DBus_helpers; using namespace DBus_helpers;
#define DBUS_TIMEOUT 2000 // ms #define DBUS_TIMEOUT 2000 // ms
struct mutexed_metadata main_metadata; struct mutexed_metadata main_metadata;
namespace dbusmgr { namespace dbusmgr {
dbus_manager dbus_mgr; dbus_manager dbus_mgr;
} }
template<class T> template <class T>
static void assign_metadata_value(metadata& meta, const std::string& key, const T& value) { static void assign_metadata_value(metadata& meta, const std::string& key,
std::cerr << "Assigning Metadata: " << key << " -> " << value << "\n"; const T& value) {
if(key == "PlaybackStatus") { if (key == "PlaybackStatus") {
meta.playing = (value == "Playing"); meta.playing = (value == "Playing");
meta.got_playback_data = true; meta.got_playback_data = true;
} } else if (key == "xesam:title") {
else if(key == "xesam:title"){
meta.title = value; meta.title = value;
meta.got_song_data = true; meta.got_song_data = true;
meta.valid = true; meta.valid = true;
} } else if (key == "xesam:artist") {
else if(key == "xesam:artist") {
meta.artists = value; meta.artists = value;
meta.got_song_data = true; meta.got_song_data = true;
meta.valid = true; meta.valid = true;
} } else if (key == "xesam:album") {
else if(key == "xesam:album") {
meta.album = value; meta.album = value;
meta.got_song_data = true; meta.got_song_data = true;
meta.valid = true; meta.valid = true;
} } else if (key == "mpris:artUrl") {
else if(key == "mpris:artUrl"){
meta.artUrl = value; meta.artUrl = value;
meta.got_song_data = true; meta.got_song_data = true;
} }
} }
std::string format_signal(const dbusmgr::DBusSignal& s) std::string format_signal(const dbusmgr::DBusSignal& s) {
{
std::stringstream ss; std::stringstream ss;
ss << "type='signal',interface='" << s.intf << "'"; ss << "type='signal',interface='" << s.intf << "'";
ss << ",member='" << s.signal << "'"; ss << ",member='" << s.signal << "'";
return ss.str(); return ss.str();
} }
static void parse_mpris_properties(libdbus_loader& dbus, DBusMessage *msg, std::string& source, metadata& meta) static void parse_mpris_properties(libdbus_loader& dbus, DBusMessage* msg,
{ std::string& source, metadata& meta) {
/** /**
* Expected response Format: * Expected response Format:
* string, * string,
@ -61,55 +57,43 @@ static void parse_mpris_properties(libdbus_loader& dbus, DBusMessage *msg, std::
* "Metadata" -> multimap, * "Metadata" -> multimap,
* "PlaybackStatus" -> string * "PlaybackStatus" -> string
* } * }
*/ */
std::string key, val; std::string key, val;
auto iter = DBusMessageIter_wrap(msg, &dbus); auto iter = DBusMessageIter_wrap(msg, &dbus);
// Should be 'org.mpris.MediaPlayer2.Player' // Should be 'org.mpris.MediaPlayer2.Player'
if (not iter.is_string()){ if (not iter.is_string()) {
std::cerr << "Not a string\n"; //TODO std::cerr << "Not a string\n"; // TODO
return; return;
} }
source = iter.get_primitive<std::string>(); source = iter.get_primitive<std::string>();
if (source != "org.mpris.MediaPlayer2.Player") if (source != "org.mpris.MediaPlayer2.Player") return;
return;
iter.next(); iter.next();
if (not iter.is_array()) if (not iter.is_array()) return;
return;
iter.string_map_for_each([&](std::string& key, DBusMessageIter_wrap it) {
//std::cerr << "Parsing mpris update...\n"; if (key == "Metadata") {
string_map_for_each(iter, [&](std::string& key, DBusMessageIter_wrap it){ it.string_map_for_each([&](const std::string& key,
if(key == "Metadata"){ DBusMessageIter_wrap it) {
//std::cerr << "\tMetadata:\n"; std::string val;
string_map_for_each(it, [&](const std::string& key, DBusMessageIter_wrap it){ if (it.is_primitive()) {
if(it.is_primitive()){ val = it.get_stringified();
auto val = it.get_stringified(); } else if (it.is_array()) {
//std::cerr << "\t\t" << key << " -> " << val << "\n"; it.array_for_each_stringify([&](const std::string& str) {
assign_metadata_value(meta, key, val); if (val.empty()) {
}
else if(it.is_array()){
std::string val;
array_for_each_stringify(it, [&](const std::string& str){
if(val.empty()){
val = str; val = str;
} } else {
else {
val += ", " + str; val += ", " + str;
} }
}); });
//std::cerr << "\t\t" << key << " -> " << val << "\n";
assign_metadata_value(meta, key, val);
} }
});
string_multimap_for_each_stringify(it, [&](const std::string& key, const std::string& val){
assign_metadata_value(meta, key, val); assign_metadata_value(meta, key, val);
}); });
} } else if (key == "PlaybackStatus") {
else if(key == "PlaybackStatus"){
auto val = it.get_stringified(); auto val = it.get_stringified();
assign_metadata_value(meta, key, val); assign_metadata_value(meta, key, val);
} }
@ -117,47 +101,43 @@ static void parse_mpris_properties(libdbus_loader& dbus, DBusMessage *msg, std::
meta.valid = (meta.artists.size() || !meta.title.empty()); meta.valid = (meta.artists.size() || !meta.title.empty());
} }
bool dbus_get_name_owner(dbusmgr::dbus_manager& dbus_mgr, std::string& name_owner, const char *name) bool dbus_get_name_owner(dbusmgr::dbus_manager& dbus_mgr,
{ std::string& name_owner, const char* name) {
auto reply = DBusMessage_wrap::new_method_call( auto reply =
"org.freedesktop.DBus", DBusMessage_wrap::new_method_call(
"/org/freedesktop/DBus", "org.freedesktop.DBus", "/org/freedesktop/DBus",
"org.freedesktop.DBus", "org.freedesktop.DBus", "GetNameOwner", &dbus_mgr.dbus())
"GetNameOwner", .argument(name)
&dbus_mgr.dbus() .send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
).argument(name).send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT); if (not reply) return false;
if(not reply) return false;
auto iter = reply.iter(); auto iter = reply.iter();
if(not iter.is_string()) return false; if (not iter.is_string()) return false;
name_owner = iter.get_primitive<std::string>(); name_owner = iter.get_primitive<std::string>();
return true; return true;
} }
bool dbus_get_player_property(dbusmgr::dbus_manager& dbus_mgr, metadata& meta, const char * dest, const char * prop) bool dbus_get_player_property(dbusmgr::dbus_manager& dbus_mgr, metadata& meta,
{ const char* dest, const char* prop) {
auto reply = DBusMessage_wrap::new_method_call( auto reply =
dest, DBusMessage_wrap::new_method_call(dest, "/org/mpris/MediaPlayer2",
"/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties",
"org.freedesktop.DBus.Properties", "Get", &dbus_mgr.dbus())
"Get", .argument("org.mpris.MediaPlayer2.Player")
&dbus_mgr.dbus() .argument(prop)
).argument("org.mpris.MediaPlayer2.Player") .send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
.argument(prop)
.send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
if(not reply) return false; if (not reply) return false;
auto iter = reply.iter(); auto iter = reply.iter();
if(iter.is_array()){ if (iter.is_array()) {
string_multimap_for_each_stringify(iter, [&](const std::string& key, const std::string& val){ iter.string_multimap_for_each_stringify(
assign_metadata_value(meta, key, val); [&](const std::string& key, const std::string& val) {
}); assign_metadata_value(meta, key, val);
} });
else if(iter.is_primitive()){ } else if (iter.is_primitive()) {
assign_metadata_value(meta, prop, iter.get_stringified()); assign_metadata_value(meta, prop, iter.get_stringified());
} } else {
else {
return false; return false;
} }
return true; return true;
@ -165,8 +145,8 @@ bool dbus_get_player_property(dbusmgr::dbus_manager& dbus_mgr, metadata& meta, c
namespace dbusmgr { namespace dbusmgr {
bool dbus_manager::get_media_player_metadata(metadata& meta, std::string name) { bool dbus_manager::get_media_player_metadata(metadata& meta, std::string name) {
if(name == "") name = m_active_player; if (name == "") name = m_active_player;
if(name == "") return false; if (name == "") return false;
meta.clear(); meta.clear();
dbus_get_player_property(*this, meta, name.c_str(), "Metadata"); dbus_get_player_property(*this, meta, name.c_str(), "Metadata");
dbus_get_player_property(*this, meta, name.c_str(), "PlaybackStatus"); dbus_get_player_property(*this, meta, name.c_str(), "PlaybackStatus");
@ -174,11 +154,9 @@ bool dbus_manager::get_media_player_metadata(metadata& meta, std::string name) {
return true; return true;
} }
bool dbus_manager::init(const std::string& requested_player) bool dbus_manager::init(const std::string& requested_player) {
{ if (m_inited) return true;
if (m_inited)
return true;
m_requested_player = "org.mpris.MediaPlayer2." + requested_player; m_requested_player = "org.mpris.MediaPlayer2." + requested_player;
if (!m_dbus_ldr.IsLoaded() && !m_dbus_ldr.Load("libdbus-1.so.3")) { if (!m_dbus_ldr.IsLoaded() && !m_dbus_ldr.Load("libdbus-1.so.3")) {
@ -190,60 +168,65 @@ bool dbus_manager::init(const std::string& requested_player)
m_dbus_ldr.threads_init_default(); m_dbus_ldr.threads_init_default();
if ( nullptr == (m_dbus_conn = m_dbus_ldr.bus_get(DBUS_BUS_SESSION, &m_error)) ) { if (nullptr ==
(m_dbus_conn = m_dbus_ldr.bus_get(DBUS_BUS_SESSION, &m_error))) {
std::cerr << "MANGOHUD: " << m_error.message << std::endl; std::cerr << "MANGOHUD: " << m_error.message << std::endl;
m_dbus_ldr.error_free(&m_error); m_dbus_ldr.error_free(&m_error);
return false; return false;
} }
std::cout << "MANGOHUD: Connected to D-Bus as \"" << m_dbus_ldr.bus_get_unique_name(m_dbus_conn) << "\"." << std::endl; std::cout << "MANGOHUD: Connected to D-Bus as \""
<< m_dbus_ldr.bus_get_unique_name(m_dbus_conn) << "\"."
<< std::endl;
dbus_list_name_to_owner(); dbus_list_name_to_owner();
connect_to_signals(); connect_to_signals();
select_active_player(); select_active_player();
{
std::lock_guard<std::mutex> lck(main_metadata.mtx);
get_media_player_metadata(main_metadata.meta);
}
m_inited = true; m_inited = true;
return true; return true;
} }
bool dbus_manager::select_active_player(metadata* store_meta) { bool dbus_manager::select_active_player() {
auto old_active_player = m_active_player;
m_active_player = "";
metadata meta{};
// If the requested player is available, use it // If the requested player is available, use it
if(m_name_owners.count(m_requested_player) > 0) { if (m_name_owners.count(m_requested_player) > 0) {
m_active_player = m_requested_player; m_active_player = m_requested_player;
std::cerr << "Selecting requested player: " << m_requested_player << "\n"; std::cerr << "Selecting requested player: " << m_requested_player
if(store_meta) get_media_player_metadata(*store_meta, m_active_player); << "\n";
return true; get_media_player_metadata(meta, m_active_player);
} }
// Else, use any player that is currently playing.. // Else, use any player that is currently playing..
for(const auto& entry : m_name_owners) { if (m_active_player.empty()) {
const auto& name = std::get<0>(entry); for (const auto& entry : m_name_owners) {
metadata meta; const auto& name = std::get<0>(entry);
get_media_player_metadata(meta, name); get_media_player_metadata(meta, name);
if(meta.playing) { if (meta.playing) {
m_active_player = name; m_active_player = name;
std::cerr << "Selecting fallback player: " << name << "\n"; std::cerr << "Selecting fallback player: " << name << "\n";
if(store_meta) *store_meta = meta; }
return true;
} }
} }
// No media players are active if (not m_active_player.empty()) {
std::cerr << "No active players\n"; if (m_active_player != old_active_player) {
m_active_player = ""; onNewPlayer(meta);
if(store_meta) store_meta->clear(); }
return false; return true;
} else {
std::cerr << "No active players\n";
if (not old_active_player.empty()) {
onNoPlayer();
}
return false;
}
} }
void dbus_manager::deinit() void dbus_manager::deinit() {
{ if (!m_inited) return;
if (!m_inited)
return;
// unreference system bus connection instead of closing it // unreference system bus connection instead of closing it
if (m_dbus_conn) { if (m_dbus_conn) {
@ -255,18 +238,17 @@ void dbus_manager::deinit()
m_inited = false; m_inited = false;
} }
dbus_manager::~dbus_manager() dbus_manager::~dbus_manager() { deinit(); }
{
deinit();
}
DBusHandlerResult dbus_manager::filter_signals(DBusConnection* conn, DBusMessage* msg, void* userData) { DBusHandlerResult dbus_manager::filter_signals(DBusConnection* conn,
DBusMessage* msg,
void* userData) {
auto& manager = *reinterpret_cast<dbus_manager*>(userData); auto& manager = *reinterpret_cast<dbus_manager*>(userData);
for(auto& sig : manager.m_signals) { for (auto& sig : manager.m_signals) {
if(manager.m_dbus_ldr.message_is_signal(msg, sig.intf, sig.signal)){ if (manager.m_dbus_ldr.message_is_signal(msg, sig.intf, sig.signal)) {
auto sender = manager.m_dbus_ldr.message_get_sender(msg); auto sender = manager.m_dbus_ldr.message_get_sender(msg);
if((manager.*(sig.handler))(msg, sender)) if ((manager.*(sig.handler))(msg, sender))
return DBUS_HANDLER_RESULT_HANDLED; return DBUS_HANDLER_RESULT_HANDLED;
else else
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@ -275,7 +257,8 @@ DBusHandlerResult dbus_manager::filter_signals(DBusConnection* conn, DBusMessage
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} }
bool dbus_manager::handle_properties_changed(DBusMessage* msg, const char* sender) { bool dbus_manager::handle_properties_changed(DBusMessage* msg,
const char* sender) {
std::string source; std::string source;
metadata meta; metadata meta;
@ -284,88 +267,49 @@ bool dbus_manager::handle_properties_changed(DBusMessage* msg, const char* sende
std::cerr << "PropertiesChanged Signal received:\n"; std::cerr << "PropertiesChanged Signal received:\n";
std::cerr << "\tSource: " << source << "\n"; std::cerr << "\tSource: " << source << "\n";
std::cerr << "active_player: " << m_active_player << "\n"; std::cerr << "active_player: " << m_active_player << "\n";
std::cerr << "active_player's owner: " << m_name_owners[m_active_player] << "\n"; std::cerr << "active_player's owner: " << m_name_owners[m_active_player]
<< "\n";
std::cerr << "sender: " << sender << "\n"; std::cerr << "sender: " << sender << "\n";
#endif #endif
if (source != "org.mpris.MediaPlayer2.Player") if (source != "org.mpris.MediaPlayer2.Player") return false;
return false;
if(m_active_player == "") { if (m_active_player == "") {
select_active_player(&meta); select_active_player();
} else if (m_name_owners[m_active_player] == sender) {
onPlayerUpdate(meta);
} }
if (m_name_owners[m_active_player] == sender) {
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;
}
}
std::cerr << "Main metadata valid: " << std::boolalpha << main_metadata.meta.valid << "\n";
return true; return true;
} }
bool dbus_manager::handle_name_owner_changed(DBusMessage* msg, const char* sender) { bool dbus_manager::handle_name_owner_changed(DBusMessage* _msg,
DBusMessageIter iter; const char* sender) {
m_dbus_ldr.message_iter_init (msg, &iter);
std::vector<std::string> str; std::vector<std::string> str;
const char *value = nullptr;
while (m_dbus_ldr.message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) { for (auto iter = DBusMessageIter_wrap(_msg, &m_dbus_ldr); iter;
m_dbus_ldr.message_iter_get_basic (&iter, &value); iter.next()) {
str.push_back(value); str.push_back(iter.get_primitive<std::string>());
m_dbus_ldr.message_iter_next (&iter);
} }
// register new name // register new name
if (str.size() == 3 if (str.size() == 3 && starts_with(str[0], "org.mpris.MediaPlayer2.") &&
&& starts_with(str[0], "org.mpris.MediaPlayer2.") !str[2].empty()) {
&& !str[2].empty()
)
{
m_name_owners[str[0]] = str[2]; m_name_owners[str[0]] = str[2];
if(str[0] == m_requested_player){ if (str[0] == m_requested_player) {
metadata tmp; select_active_player();
select_active_player(&tmp);
{
std::lock_guard<std::mutex> lck(main_metadata.mtx);
main_metadata.meta = tmp;
main_metadata.ticker = {};
}
} }
} }
// did a player quit? // did a player quit?
if (str[2].empty()) { if (str[2].empty()) {
if (str.size() == 3 if (str.size() == 3 && str[0] == m_active_player) {
&& str[0] == m_active_player
) {
metadata tmp;
m_name_owners.erase(str[0]); m_name_owners.erase(str[0]);
select_active_player(); select_active_player();
get_media_player_metadata(tmp);
{
std::lock_guard<std::mutex> lck(main_metadata.mtx);
std::swap(tmp, main_metadata.meta);
}
} }
} }
return true; return true;
} }
void dbus_manager::connect_to_signals() void dbus_manager::connect_to_signals() {
{
for (auto kv : m_signals) { for (auto kv : m_signals) {
auto signal = format_signal(kv); auto signal = format_signal(kv);
m_dbus_ldr.bus_add_match(m_dbus_conn, signal.c_str(), &m_error); m_dbus_ldr.bus_add_match(m_dbus_conn, signal.c_str(), &m_error);
@ -373,17 +317,18 @@ void dbus_manager::connect_to_signals()
::perror(m_error.name); ::perror(m_error.name);
::perror(m_error.message); ::perror(m_error.message);
m_dbus_ldr.error_free(&m_error); m_dbus_ldr.error_free(&m_error);
//return; // return;
} }
} }
m_dbus_ldr.connection_add_filter(m_dbus_conn, filter_signals, reinterpret_cast<void*>(this), nullptr); m_dbus_ldr.connection_add_filter(m_dbus_conn, filter_signals,
reinterpret_cast<void*>(this), nullptr);
start_thread(); start_thread();
} }
void dbus_manager::disconnect_from_signals() void dbus_manager::disconnect_from_signals() {
{ m_dbus_ldr.connection_remove_filter(m_dbus_conn, filter_signals,
m_dbus_ldr.connection_remove_filter(m_dbus_conn, filter_signals, reinterpret_cast<void*>(this)); reinterpret_cast<void*>(this));
for (auto kv : m_signals) { for (auto kv : m_signals) {
auto signal = format_signal(kv); auto signal = format_signal(kv);
m_dbus_ldr.bus_remove_match(m_dbus_conn, signal.c_str(), &m_error); m_dbus_ldr.bus_remove_match(m_dbus_conn, signal.c_str(), &m_error);
@ -397,51 +342,74 @@ void dbus_manager::disconnect_from_signals()
stop_thread(); stop_thread();
} }
bool dbus_manager::dbus_list_name_to_owner() bool dbus_manager::dbus_list_name_to_owner() {
{ auto reply =
auto reply = DBusMessage_wrap::new_method_call( DBusMessage_wrap::new_method_call(
"org.freedesktop.DBus", "org.freedesktop.DBus", "/org/freedesktop/DBus",
"/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", &dbus_mgr.dbus())
"org.freedesktop.DBus", .send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
"ListNames", if (not reply) return false;
&dbus_mgr.dbus()
).send_with_reply_and_block(dbus_mgr.get_conn(), DBUS_TIMEOUT);
if(not reply) return false;
auto iter = reply.iter(); auto iter = reply.iter();
if(not iter.is_array()) { if (not iter.is_array()) {
return false; return false;
} }
array_for_each<std::string>(iter, [&](std::string name){ iter.array_for_each_value<std::string>([&](std::string name) {
if(!starts_with(name.c_str(), "org.mpris.MediaPlayer2.")) return; if (!starts_with(name.c_str(), "org.mpris.MediaPlayer2.")) return;
std::string owner; std::string owner;
if(dbus_get_name_owner(dbus_mgr, owner, name.c_str())){ if (dbus_get_name_owner(dbus_mgr, owner, name.c_str())) {
m_name_owners[name] = owner; m_name_owners[name] = owner;
} }
}); });
return true; return true;
} }
void dbus_manager::stop_thread() void dbus_manager::stop_thread() {
{
m_quit = true; m_quit = true;
if (m_thread.joinable()) if (m_thread.joinable()) m_thread.join();
m_thread.join();
} }
void dbus_manager::start_thread() void dbus_manager::start_thread() {
{
stop_thread(); stop_thread();
m_quit = false; m_quit = false;
m_thread = std::thread(&dbus_manager::dbus_thread, this); m_thread = std::thread(&dbus_manager::dbus_thread, this);
} }
void dbus_manager::dbus_thread() void dbus_manager::dbus_thread() {
{
using namespace std::chrono_literals; using namespace std::chrono_literals;
while(!m_quit && m_dbus_ldr.connection_read_write_dispatch(m_dbus_conn, 0)) while (!m_quit && m_dbus_ldr.connection_read_write_dispatch(m_dbus_conn, 0))
std::this_thread::sleep_for(10ms); std::this_thread::sleep_for(10ms);
} }
void dbus_manager::onNoPlayer() {
std::lock_guard<std::mutex> lck(main_metadata.mtx);
main_metadata.meta = {};
main_metadata.ticker = {};
} }
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

@ -2,83 +2,86 @@
#ifndef MANGOHUD_DBUS_HELPERS #ifndef MANGOHUD_DBUS_HELPERS
#define MANGOHUD_DBUS_HELPERS #define MANGOHUD_DBUS_HELPERS
#include <vector>
#include "loaders/loader_dbus.h" #include "loaders/loader_dbus.h"
namespace DBus_helpers{ namespace DBus_helpers {
namespace detail{ namespace detail {
template<class T> struct dbus_type_identifier{}; // clang-format off
template<> struct dbus_type_identifier<uint8_t> { const int value = DBUS_TYPE_BYTE; }; template<class T> struct dbus_type_traits{};
template<> struct dbus_type_identifier<uint16_t> { const int value = DBUS_TYPE_UINT16; }; template<> struct dbus_type_traits<uint8_t> { const int value = DBUS_TYPE_BYTE; const bool is_fixed = true; };
template<> struct dbus_type_identifier<uint32_t> { const int value = DBUS_TYPE_UINT32; }; template<> struct dbus_type_traits<uint16_t> { const int value = DBUS_TYPE_UINT16; const bool is_fixed = true; };
template<> struct dbus_type_identifier<uint64_t> { const int value = DBUS_TYPE_UINT64; }; template<> struct dbus_type_traits<uint32_t> { const int value = DBUS_TYPE_UINT32; const bool is_fixed = true; };
template<> struct dbus_type_identifier<int16_t> { const int value = DBUS_TYPE_INT16; }; template<> struct dbus_type_traits<uint64_t> { const int value = DBUS_TYPE_UINT64; const bool is_fixed = true; };
template<> struct dbus_type_identifier<int32_t> { const int value = DBUS_TYPE_INT32; }; template<> struct dbus_type_traits<int16_t> { const int value = DBUS_TYPE_INT16; const bool is_fixed = true; };
template<> struct dbus_type_identifier<int64_t> { const int value = DBUS_TYPE_INT64; }; template<> struct dbus_type_traits<int32_t> { const int value = DBUS_TYPE_INT32; const bool is_fixed = true; };
template<> struct dbus_type_identifier<double> { const int value = DBUS_TYPE_DOUBLE; }; template<> struct dbus_type_traits<int64_t> { const int value = DBUS_TYPE_INT64; const bool is_fixed = true; };
template<> struct dbus_type_identifier<const char*> { const int value = DBUS_TYPE_STRING; }; template<> struct dbus_type_traits<double> { const int value = DBUS_TYPE_DOUBLE; const bool is_fixed = true; };
template<> struct dbus_type_traits<const char*> { const int value = DBUS_TYPE_STRING; const bool is_fixed = false; };
template<class T> // clang-format on
const int dbus_type_identifier_v = dbus_type_identifier<T>().value;
} //namespace detail template <class T>
const int dbus_type_identifier = dbus_type_traits<T>().value;
template <class T>
const bool is_fixed = dbus_type_traits<T>().is_fiexd;
} // namespace detail
class DBusMessageIter_wrap { class DBusMessageIter_wrap {
public:
DBusMessageIter_wrap(DBusMessage* msg, libdbus_loader* loader);
DBusMessageIter_wrap(DBusMessageIter iter, libdbus_loader* loader);
public: // Type accessors
DBusMessageIter_wrap(DBusMessage* msg, libdbus_loader* loader) int type() const noexcept { return m_type; }
{
m_DBus = loader;
if(msg){
m_DBus->message_iter_init(msg, &m_Iter);
m_resolved_iter = resolve_variants();
m_type = m_DBus->message_iter_get_arg_type(&m_resolved_iter);
}
else {
m_type = DBUS_TYPE_INVALID;
}
}
DBusMessageIter_wrap(DBusMessageIter iter, libdbus_loader* loader)
: m_Iter(iter), m_DBus(loader)
{
m_resolved_iter = resolve_variants();
m_type = m_DBus->message_iter_get_arg_type(&m_resolved_iter);
}
int type() const noexcept { return m_type; }
bool is_unsigned() const noexcept; bool is_unsigned() const noexcept;
bool is_signed() const noexcept; bool is_signed() const noexcept;
bool is_string() const noexcept; bool is_string() const noexcept;
bool is_double() const noexcept; bool is_double() const noexcept;
bool is_primitive() const noexcept; bool is_primitive() const noexcept;
bool is_array() const noexcept; bool is_array() const noexcept;
operator bool() const noexcept { operator bool() const noexcept { return type() != DBUS_TYPE_INVALID; }
return type() != DBUS_TYPE_INVALID;
}
// Value accessors
template<class T> // Primitives
template <class T>
auto get_primitive() -> T; auto get_primitive() -> T;
auto get_unsigned() -> uint64_t; auto get_unsigned() -> uint64_t;
auto get_signed() -> int64_t; auto get_signed() -> int64_t;
auto get_stringified() -> std::string; auto get_stringified() -> std::string;
// Composites
auto get_array_iter() -> DBusMessageIter_wrap; auto get_array_iter() -> DBusMessageIter_wrap;
auto get_dict_entry_iter() -> DBusMessageIter_wrap; auto get_dict_entry_iter() -> DBusMessageIter_wrap;
// Looping
template <class Callable>
void array_for_each(Callable);
template <class Callable>
void array_for_each_stringify(Callable);
template <class T, class Callable>
void array_for_each_value(Callable);
template <class Callable>
void string_map_for_each(Callable);
template <class Callable>
void string_multimap_for_each_stringify(Callable);
auto next() { auto next() {
if (not *this) return *this;
m_DBus->message_iter_next(&m_Iter); m_DBus->message_iter_next(&m_Iter);
// Resolve any variants // Resolve any variants
m_resolved_iter = resolve_variants(); m_resolved_iter = resolve_variants();
m_type = m_DBus->message_iter_get_arg_type(&m_resolved_iter); m_type = m_DBus->message_iter_get_arg_type(&m_resolved_iter);
return *this; return *this;
} }
private:
private:
DBusMessageIter resolve_variants() { DBusMessageIter resolve_variants() {
auto iter = m_Iter; auto iter = m_Iter;
auto field_type = m_DBus->message_iter_get_arg_type(&m_Iter); auto field_type = m_DBus->message_iter_get_arg_type(&m_Iter);
while(field_type == DBUS_TYPE_VARIANT){ while (field_type == DBUS_TYPE_VARIANT) {
m_DBus->message_iter_recurse(&iter, &iter); m_DBus->message_iter_recurse(&iter, &iter);
field_type = m_DBus->message_iter_get_arg_type(&iter); field_type = m_DBus->message_iter_get_arg_type(&iter);
} }
@ -91,23 +94,33 @@ private:
libdbus_loader* m_DBus; libdbus_loader* m_DBus;
}; };
DBusMessageIter_wrap::DBusMessageIter_wrap(DBusMessage* msg,
libdbus_loader* loader) {
m_DBus = loader;
if (msg) {
m_DBus->message_iter_init(msg, &m_Iter);
m_resolved_iter = resolve_variants();
m_type = m_DBus->message_iter_get_arg_type(&m_resolved_iter);
} else {
m_type = DBUS_TYPE_INVALID;
}
}
DBusMessageIter_wrap::DBusMessageIter_wrap(DBusMessageIter iter,
libdbus_loader* loader)
: m_Iter(iter), m_DBus(loader) {
m_resolved_iter = resolve_variants();
m_type = m_DBus->message_iter_get_arg_type(&m_resolved_iter);
}
bool DBusMessageIter_wrap::is_unsigned() const noexcept { bool DBusMessageIter_wrap::is_unsigned() const noexcept {
return ( return ((type() == DBUS_TYPE_BYTE) || (type() == DBUS_TYPE_INT16) ||
(type() == DBUS_TYPE_BYTE) || (type() == DBUS_TYPE_INT32) || (type() == DBUS_TYPE_INT64));
(type() == DBUS_TYPE_INT16) ||
(type() == DBUS_TYPE_INT32) ||
(type() == DBUS_TYPE_INT64)
);
} }
bool DBusMessageIter_wrap::is_signed() const noexcept { bool DBusMessageIter_wrap::is_signed() const noexcept {
return ( return ((type() == DBUS_TYPE_INT16) || (type() == DBUS_TYPE_INT32) ||
(type() == DBUS_TYPE_INT16) || (type() == DBUS_TYPE_INT64));
(type() == DBUS_TYPE_INT32) ||
(type() == DBUS_TYPE_INT64)
);
} }
bool DBusMessageIter_wrap::is_string() const noexcept { bool DBusMessageIter_wrap::is_string() const noexcept {
@ -119,24 +132,19 @@ bool DBusMessageIter_wrap::is_double() const noexcept {
} }
bool DBusMessageIter_wrap::is_primitive() const noexcept { bool DBusMessageIter_wrap::is_primitive() const noexcept {
return ( return (is_double() || is_signed() || is_unsigned() || is_string());
is_double() ||
is_signed() ||
is_unsigned() ||
is_string()
);
} }
bool DBusMessageIter_wrap::is_array() const noexcept { bool DBusMessageIter_wrap::is_array() const noexcept {
return (type() == DBUS_TYPE_ARRAY); return (type() == DBUS_TYPE_ARRAY);
} }
template <class T>
template<class T>
auto DBusMessageIter_wrap::get_primitive() -> T { auto DBusMessageIter_wrap::get_primitive() -> T {
auto requested_type = detail::dbus_type_identifier_v<T>; auto requested_type = detail::dbus_type_identifier<T>;
if(requested_type != type()){ if (requested_type != type()) {
std::cerr << "Type mismatch: '" << (char) requested_type << "' vs '" << (char) type() << "'\n"; std::cerr << "Type mismatch: '" << ((char)requested_type) << "' vs '"
<< (char)type() << "'";
#ifndef NDEBUG #ifndef NDEBUG
exit(-1); exit(-1);
#else #else
@ -149,55 +157,53 @@ auto DBusMessageIter_wrap::get_primitive() -> T {
return ret; return ret;
} }
template<> template <>
auto DBusMessageIter_wrap::get_primitive<std::string>() -> std::string { auto DBusMessageIter_wrap::get_primitive<std::string>() -> std::string {
return std::string(get_primitive<const char*>()); return std::string(get_primitive<const char*>());
} }
uint64_t DBusMessageIter_wrap::get_unsigned() { uint64_t DBusMessageIter_wrap::get_unsigned() {
auto t = type(); auto t = type();
switch (t) switch (t) {
{ case DBUS_TYPE_BYTE:
case DBUS_TYPE_BYTE: return get_primitive<uint8_t>();
return get_primitive<uint8_t>(); case DBUS_TYPE_UINT16:
case DBUS_TYPE_UINT16: return get_primitive<uint16_t>();
return get_primitive<uint16_t>(); case DBUS_TYPE_UINT32:
case DBUS_TYPE_UINT32: return get_primitive<uint32_t>();
return get_primitive<uint32_t>(); case DBUS_TYPE_UINT64:
case DBUS_TYPE_UINT64: return get_primitive<uint64_t>();
return get_primitive<uint64_t>(); default:
default: return 0;
return 0;
} }
} }
int64_t DBusMessageIter_wrap::get_signed() { int64_t DBusMessageIter_wrap::get_signed() {
auto t = type(); auto t = type();
switch (t) switch (t) {
{ case DBUS_TYPE_INT16:
case DBUS_TYPE_INT16: return get_primitive<int16_t>();
return get_primitive<int16_t>(); case DBUS_TYPE_INT32:
case DBUS_TYPE_INT32: return get_primitive<int32_t>();
return get_primitive<int32_t>(); case DBUS_TYPE_INT64:
case DBUS_TYPE_INT64: return get_primitive<int64_t>();
return get_primitive<int64_t>(); default:
default: return 0;
return 0;
} }
} }
auto DBusMessageIter_wrap::get_stringified() -> std::string { auto DBusMessageIter_wrap::get_stringified() -> std::string {
if(is_string()) return get_primitive<std::string>(); if (is_string()) return get_primitive<std::string>();
if(is_unsigned()) return std::to_string(get_unsigned()); if (is_unsigned()) return std::to_string(get_unsigned());
if(is_signed()) return std::to_string(get_signed()); if (is_signed()) return std::to_string(get_signed());
if(is_double()) return std::to_string(get_primitive<double>()); if (is_double()) return std::to_string(get_primitive<double>());
std::cerr << "stringify failed\n"; std::cerr << "stringify failed\n";
return std::string(); return std::string();
} }
auto DBusMessageIter_wrap::get_array_iter() -> DBusMessageIter_wrap { auto DBusMessageIter_wrap::get_array_iter() -> DBusMessageIter_wrap {
if(not is_array()) { if (not is_array()) {
std::cerr << "Not an array\n"; std::cerr << "Not an array; " << (char)type() << "\n";
return DBusMessageIter_wrap(DBusMessageIter{}, m_DBus); return DBusMessageIter_wrap(DBusMessageIter{}, m_DBus);
} }
@ -207,8 +213,8 @@ auto DBusMessageIter_wrap::get_array_iter() -> DBusMessageIter_wrap {
} }
auto DBusMessageIter_wrap::get_dict_entry_iter() -> DBusMessageIter_wrap { auto DBusMessageIter_wrap::get_dict_entry_iter() -> DBusMessageIter_wrap {
if(type() != DBUS_TYPE_DICT_ENTRY){ if (type() != DBUS_TYPE_DICT_ENTRY) {
std::cerr << "Not a dict entry\n"; std::cerr << "Not a dict entry" << (char)type() << "\n";
return DBusMessageIter_wrap(DBusMessageIter{}, m_DBus); return DBusMessageIter_wrap(DBusMessageIter{}, m_DBus);
} }
@ -217,146 +223,139 @@ auto DBusMessageIter_wrap::get_dict_entry_iter() -> DBusMessageIter_wrap {
return DBusMessageIter_wrap(ret, m_DBus); return DBusMessageIter_wrap(ret, m_DBus);
} }
template <class T, class Callable>
void DBusMessageIter_wrap::array_for_each_value(Callable action) {
auto iter = get_array_iter();
for (; iter; iter.next()) {
action(iter.get_primitive<T>());
// Precondition: iter points to a dict of string -> any
// executes action(key, value_iter) for all entries
template<class T>
void string_map_for_each(DBusMessageIter_wrap iter, T action) {
iter = iter.get_array_iter();
for(; iter; iter.next()) {
auto it = iter.get_dict_entry_iter();
auto key = it.get_primitive<std::string>();
it.next();
action(key, it);
} }
} }
template<class T, class Callable> template <class Callable>
void array_for_each(DBusMessageIter_wrap iter, Callable action) { void DBusMessageIter_wrap::array_for_each(Callable action) {
iter = iter.get_array_iter(); auto iter = get_array_iter();
for(; iter; iter.next()){ for (; iter; iter.next()) {
action(iter.get_primitive<T>()); action(iter);
} }
} }
template<class Callable> template <class Callable>
void array_for_each_stringify(DBusMessageIter_wrap iter, Callable action) { void DBusMessageIter_wrap::array_for_each_stringify(Callable action) {
iter = iter.get_array_iter(); auto iter = get_array_iter();
for(; iter; iter.next()){ for (; iter; iter.next()) {
action(iter.get_stringified()); action(iter.get_stringified());
} }
} }
template<class T> template <class T>
void string_multimap_for_each_stringify(DBusMessageIter_wrap iter, T action) { void DBusMessageIter_wrap::string_map_for_each(T action) {
string_map_for_each(iter, [&](const std::string& key, DBusMessageIter_wrap it){ auto iter = get_array_iter();
if(it.is_array()){ for (; iter; iter.next()) {
array_for_each_stringify(it, [&](const std::string& val){ auto it = iter.get_dict_entry_iter();
action(key, val); auto key = it.get_primitive<std::string>();
});
} it.next();
else if(it.is_primitive()){ action(key, it);
action(key, it.get_stringified()); }
}
});
} }
template <class T>
void DBusMessageIter_wrap::string_multimap_for_each_stringify(T action) {
string_map_for_each([&action](const std::string& key, DBusMessageIter_wrap it) {
if (it.is_array()) {
it.array_for_each_stringify(
[&](const std::string& val) { action(key, val); });
} else if (it.is_primitive()) {
action(key, it.get_stringified());
}
});
}
class DBusMessage_wrap { class DBusMessage_wrap {
public: public:
DBusMessage_wrap(DBusMessage* msg, libdbus_loader* ldr, bool owning = false) DBusMessage_wrap(DBusMessage* msg, libdbus_loader* ldr, bool owning = false)
: m_owning(owning), m_msg(msg), m_DBus(ldr) : m_owning(owning), m_msg(msg), m_DBus(ldr) {}
{}
~DBusMessage_wrap(){ ~DBusMessage_wrap() { free_if_owning(); }
free_if_owning();
}
DBusMessage_wrap(const DBusMessage_wrap&) = delete; DBusMessage_wrap(const DBusMessage_wrap&) = delete;
DBusMessage_wrap(DBusMessage_wrap&&) = default; DBusMessage_wrap(DBusMessage_wrap&&) = default;
operator bool() const { operator bool() const noexcept { return m_msg != nullptr; }
return m_msg != nullptr;
}
template<class T> template <class T>
DBusMessage_wrap& argument(T arg) { DBusMessage_wrap& argument(T arg);
if(not m_msg) return *this;
if(not m_DBus->message_append_args(
m_msg,
detail::dbus_type_identifier_v<T>,
&arg,
DBUS_TYPE_INVALID
)){
free_if_owning();
}
return *this;
}
DBusMessage_wrap send_with_reply_and_block(DBusConnection* conn, int timeout) { DBusMessage_wrap send_with_reply_and_block(DBusConnection* conn,
if(not m_msg){ int timeout);
return DBusMessage_wrap(nullptr, m_DBus);
}
DBusError err;
m_DBus->error_init(&err);
auto reply = m_DBus->connection_send_with_reply_and_block(
conn,
m_msg,
timeout,
&err
);
if(reply == nullptr) {
std::cerr << "MangoHud[" << __func__ << "]: " << err.message << "\n";
free_if_owning();
m_DBus->error_free(&err);
}
return DBusMessage_wrap(reply, m_DBus, true);
}
DBusMessageIter_wrap iter() { DBusMessageIter_wrap iter() { return DBusMessageIter_wrap(m_msg, m_DBus); }
return DBusMessageIter_wrap(m_msg, m_DBus);
}
static DBusMessage_wrap new_method_call( static DBusMessage_wrap new_method_call(const std::string& bus_name,
const std::string& bus_name, const std::string& path,
const std::string& path, const std::string& iface,
const std::string& iface, const std::string& method,
const std::string& method, libdbus_loader* loader);
libdbus_loader* loader
){ private:
auto msg = loader->message_new_method_call( void free_if_owning();
(bus_name.empty()) ? nullptr : bus_name.c_str(),
path.c_str(),
(iface.empty()) ? nullptr : iface.c_str(),
method.c_str()
);
return DBusMessage_wrap(msg, loader, true);
}
private:
void free_if_owning() {
if(m_msg and m_owning) {
m_DBus->message_unref(m_msg);
}
m_msg = nullptr;
}
bool m_owning; bool m_owning;
DBusMessage* m_msg; DBusMessage* m_msg;
libdbus_loader* m_DBus; libdbus_loader* m_DBus;
std::vector<std::string> m_args; std::vector<std::string> m_args;
}; };
template<> template <class T>
DBusMessage_wrap& DBusMessage_wrap::argument<const std::string&>(const std::string& str) DBusMessage_wrap& DBusMessage_wrap::argument(T arg) {
{ if (not m_msg) return *this;
if (not m_DBus->message_append_args(m_msg, detail::dbus_type_identifier<T>,
&arg, DBUS_TYPE_INVALID)) {
free_if_owning();
}
return *this;
}
template <>
DBusMessage_wrap& DBusMessage_wrap::argument<const std::string&>(
const std::string& str) {
return argument<const char*>(str.c_str()); return argument<const char*>(str.c_str());
} }
} //namespace DBus_helpers
DBusMessage_wrap DBusMessage_wrap::send_with_reply_and_block(
DBusConnection* conn, int timeout) {
if (not m_msg) {
return DBusMessage_wrap(nullptr, m_DBus);
}
DBusError err;
m_DBus->error_init(&err);
auto reply = m_DBus->connection_send_with_reply_and_block(conn, m_msg,
timeout, &err);
if (reply == nullptr) {
std::cerr << "MangoHud[" << __func__ << "]: " << err.message << "\n";
free_if_owning();
m_DBus->error_free(&err);
}
return DBusMessage_wrap(reply, m_DBus, true);
}
DBusMessage_wrap DBusMessage_wrap::new_method_call(const std::string& bus_name,
const std::string& path,
const std::string& iface,
const std::string& method,
libdbus_loader* loader) {
auto msg = loader->message_new_method_call(
(bus_name.empty()) ? nullptr : bus_name.c_str(), path.c_str(),
(iface.empty()) ? nullptr : iface.c_str(), method.c_str());
return DBusMessage_wrap(msg, loader, true);
}
void DBusMessage_wrap::free_if_owning() {
if (m_msg and m_owning) {
m_DBus->message_unref(m_msg);
}
m_msg = nullptr;
}
} // namespace DBus_helpers
#endif //MANGOHUD_DBUS_HELPERS #endif // MANGOHUD_DBUS_HELPERS

@ -3,31 +3,31 @@
#define MANGOHUD_DBUS_INFO_H #define MANGOHUD_DBUS_INFO_H
#include <array> #include <array>
#include <stdexcept>
#include <thread>
#include <functional> #include <functional>
#include <vector>
#include <string>
#include <map> #include <map>
#include <unordered_map>
#include <mutex> #include <mutex>
#include <stdexcept>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>
#include "loaders/loader_dbus.h" #include "loaders/loader_dbus.h"
struct metadata { struct metadata {
//std::vector<std::string> artists; // std::vector<std::string> artists;
std::string artists; // pre-concatenate std::string artists; // pre-concatenate
std::string title; std::string title;
std::string album; std::string album;
std::string something; std::string something;
std::string artUrl; std::string artUrl;
bool playing = false; bool playing = false;
bool valid = false; bool valid = false;
bool got_song_data = false; bool got_song_data = false;
bool got_playback_data = false; bool got_playback_data = false;
void clear() void clear() {
{
artists.clear(); artists.clear();
title.clear(); title.clear();
album.clear(); album.clear();
@ -51,101 +51,79 @@ struct mutexed_metadata {
} ticker; } ticker;
}; };
enum SignalType enum SignalType {
{
ST_NAMEOWNERCHANGED, ST_NAMEOWNERCHANGED,
ST_PROPERTIESCHANGED, ST_PROPERTIESCHANGED,
}; };
extern struct mutexed_metadata main_metadata; extern struct mutexed_metadata main_metadata;
namespace dbusmgr { namespace dbusmgr {
class dbus_manager; class dbus_manager;
using signal_handler_func = bool (dbus_manager::*)(DBusMessage*, const char*); using signal_handler_func = bool (dbus_manager::*)(DBusMessage*, const char*);
struct DBusSignal
{
const char * intf;
const char * signal;
signal_handler_func handler;
};
using callback_func = std::function<void(/*metadata*/)>;
enum CBENUM {
CB_CONNECTED,
CB_DISCONNECTED,
CB_NEW_METADATA,
};
class dbus_manager struct DBusSignal {
{ const char* intf;
public: const char* signal;
dbus_manager() signal_handler_func handler;
{ };
}
~dbus_manager();
bool init(const std::string& requested_player);
void deinit();
bool get_media_player_metadata(metadata& meta, std::string name = "");
void add_callback(CBENUM type, callback_func func);
void connect_to_signals();
void disconnect_from_signals();
DBusConnection* get_conn() const {
return m_dbus_conn;
}
libdbus_loader& dbus() {
return m_dbus_ldr;
}
protected:
void stop_thread();
void start_thread();
void dbus_thread();
bool dbus_list_name_to_owner();
bool select_active_player(metadata* meta = nullptr);
static DBusHandlerResult filter_signals(DBusConnection*, DBusMessage*, void*);
bool handle_properties_changed(DBusMessage*, const char*);
bool handle_name_owner_changed(DBusMessage*, const char*);
DBusError m_error;
DBusConnection * m_dbus_conn = nullptr;
DBusMessage * m_dbus_msg = nullptr;
DBusMessage * m_dbus_reply = nullptr;
bool m_quit = false;
bool m_inited = false;
std::thread m_thread;
std::map<CBENUM, callback_func> m_callbacks;
libdbus_loader m_dbus_ldr;
std::unordered_map<std::string, std::string> m_name_owners;
std::string m_requested_player;
std::string m_active_player;
const std::array<DBusSignal, 2> m_signals {{
{ "org.freedesktop.DBus", "NameOwnerChanged", &dbus_manager::handle_name_owner_changed },
{ "org.freedesktop.DBus.Properties", "PropertiesChanged", &dbus_manager::handle_properties_changed },
}};
};
extern dbus_manager dbus_mgr; class dbus_manager {
} public:
dbus_manager() {}
~dbus_manager();
bool init(const std::string& requested_player);
void deinit();
bool get_media_player_metadata(metadata& meta, std::string name = "");
void connect_to_signals();
void disconnect_from_signals();
DBusConnection* get_conn() const { return m_dbus_conn; }
libdbus_loader& dbus() { return m_dbus_ldr; }
protected:
void stop_thread();
void start_thread();
void dbus_thread();
bool dbus_list_name_to_owner();
bool select_active_player();
static DBusHandlerResult filter_signals(DBusConnection*, DBusMessage*,
void*);
bool handle_properties_changed(DBusMessage*, const char*);
bool handle_name_owner_changed(DBusMessage*, const char*);
void onNewPlayer(
metadata& meta); // A different player has become the active player
void onNoPlayer(); // There is no longer any player active
void onPlayerUpdate(
metadata& meta); // The active player has sent an update
DBusError m_error;
DBusConnection* m_dbus_conn = nullptr;
bool m_quit = false;
bool m_inited = false;
std::thread m_thread;
libdbus_loader m_dbus_ldr;
std::unordered_map<std::string, std::string> m_name_owners;
std::string m_requested_player;
std::string m_active_player;
const std::array<DBusSignal, 2> m_signals{{
{"org.freedesktop.DBus", "NameOwnerChanged",
&dbus_manager::handle_name_owner_changed},
{"org.freedesktop.DBus.Properties", "PropertiesChanged",
&dbus_manager::handle_properties_changed},
}};
};
<<<<<<< HEAD extern dbus_manager dbus_mgr;
} // namespace dbusmgr
bool get_media_player_metadata(dbusmgr::dbus_manager& dbus, const std::string& name, metadata& meta); bool get_media_player_metadata(dbusmgr::dbus_manager& dbus, const std::string& name, metadata& meta);
#endif //MANGOHUD_DBUS_INFO_H #endif //MANGOHUD_DBUS_INFO_H
=======
//bool get_media_player_metadata(dbusmgr::dbus_manager& dbus, const std::string& name, metadata& meta);
>>>>>>> 9c064df... Change the media player functionality to allow changing active media

Loading…
Cancel
Save