|
|
|
@ -1,59 +1,55 @@
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <array>
|
|
|
|
|
|
|
|
|
|
#include "dbus_helpers.hpp"
|
|
|
|
|
#include "dbus_info.h"
|
|
|
|
|
#include "string_utils.h"
|
|
|
|
|
#include "dbus_helpers.hpp"
|
|
|
|
|
|
|
|
|
|
using ms = std::chrono::milliseconds;
|
|
|
|
|
using namespace DBus_helpers;
|
|
|
|
|
#define DBUS_TIMEOUT 2000 // ms
|
|
|
|
|
#define DBUS_TIMEOUT 2000 // ms
|
|
|
|
|
|
|
|
|
|
struct mutexed_metadata main_metadata;
|
|
|
|
|
|
|
|
|
|
namespace dbusmgr {
|
|
|
|
|
namespace dbusmgr {
|
|
|
|
|
dbus_manager dbus_mgr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
static void assign_metadata_value(metadata& meta, const std::string& key, const T& value) {
|
|
|
|
|
std::cerr << "Assigning Metadata: " << key << " -> " << value << "\n";
|
|
|
|
|
if(key == "PlaybackStatus") {
|
|
|
|
|
template <class T>
|
|
|
|
|
static void assign_metadata_value(metadata& meta, const std::string& key,
|
|
|
|
|
const T& value) {
|
|
|
|
|
if (key == "PlaybackStatus") {
|
|
|
|
|
meta.playing = (value == "Playing");
|
|
|
|
|
meta.got_playback_data = true;
|
|
|
|
|
}
|
|
|
|
|
else if(key == "xesam:title"){
|
|
|
|
|
} else if (key == "xesam:title") {
|
|
|
|
|
meta.title = value;
|
|
|
|
|
meta.got_song_data = true;
|
|
|
|
|
meta.valid = true;
|
|
|
|
|
}
|
|
|
|
|
else if(key == "xesam:artist") {
|
|
|
|
|
} else if (key == "xesam:artist") {
|
|
|
|
|
meta.artists = value;
|
|
|
|
|
meta.got_song_data = true;
|
|
|
|
|
meta.valid = true;
|
|
|
|
|
}
|
|
|
|
|
else if(key == "xesam:album") {
|
|
|
|
|
} else if (key == "xesam:album") {
|
|
|
|
|
meta.album = value;
|
|
|
|
|
meta.got_song_data = true;
|
|
|
|
|
meta.valid = true;
|
|
|
|
|
}
|
|
|
|
|
else if(key == "mpris:artUrl"){
|
|
|
|
|
} else if (key == "mpris:artUrl") {
|
|
|
|
|
meta.artUrl = value;
|
|
|
|
|
meta.got_song_data = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string format_signal(const dbusmgr::DBusSignal& s)
|
|
|
|
|
{
|
|
|
|
|
std::string format_signal(const dbusmgr::DBusSignal& s) {
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
ss << "type='signal',interface='" << s.intf << "'";
|
|
|
|
|
ss << ",member='" << s.signal << "'";
|
|
|
|
|
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:
|
|
|
|
|
* string,
|
|
|
|
@ -61,55 +57,43 @@ static void parse_mpris_properties(libdbus_loader& dbus, DBusMessage *msg, std::
|
|
|
|
|
* "Metadata" -> multimap,
|
|
|
|
|
* "PlaybackStatus" -> string
|
|
|
|
|
* }
|
|
|
|
|
*/
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
std::string key, val;
|
|
|
|
|
auto iter = DBusMessageIter_wrap(msg, &dbus);
|
|
|
|
|
|
|
|
|
|
// Should be 'org.mpris.MediaPlayer2.Player'
|
|
|
|
|
if (not iter.is_string()){
|
|
|
|
|
std::cerr << "Not a string\n"; //TODO
|
|
|
|
|
if (not iter.is_string()) {
|
|
|
|
|
std::cerr << "Not a string\n"; // TODO
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
source = iter.get_primitive<std::string>();
|
|
|
|
|
|
|
|
|
|
if (source != "org.mpris.MediaPlayer2.Player")
|
|
|
|
|
return;
|
|
|
|
|
if (source != "org.mpris.MediaPlayer2.Player") return;
|
|
|
|
|
|
|
|
|
|
iter.next();
|
|
|
|
|
if (not iter.is_array())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//std::cerr << "Parsing mpris update...\n";
|
|
|
|
|
string_map_for_each(iter, [&](std::string& key, DBusMessageIter_wrap it){
|
|
|
|
|
if(key == "Metadata"){
|
|
|
|
|
//std::cerr << "\tMetadata:\n";
|
|
|
|
|
string_map_for_each(it, [&](const std::string& key, DBusMessageIter_wrap it){
|
|
|
|
|
if(it.is_primitive()){
|
|
|
|
|
auto val = it.get_stringified();
|
|
|
|
|
//std::cerr << "\t\t" << key << " -> " << val << "\n";
|
|
|
|
|
assign_metadata_value(meta, key, val);
|
|
|
|
|
}
|
|
|
|
|
else if(it.is_array()){
|
|
|
|
|
std::string val;
|
|
|
|
|
array_for_each_stringify(it, [&](const std::string& str){
|
|
|
|
|
if(val.empty()){
|
|
|
|
|
if (not iter.is_array()) return;
|
|
|
|
|
|
|
|
|
|
iter.string_map_for_each([&](std::string& key, DBusMessageIter_wrap it) {
|
|
|
|
|
if (key == "Metadata") {
|
|
|
|
|
it.string_map_for_each([&](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 {
|
|
|
|
|
} else {
|
|
|
|
|
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);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else if(key == "PlaybackStatus"){
|
|
|
|
|
} else if (key == "PlaybackStatus") {
|
|
|
|
|
auto val = it.get_stringified();
|
|
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool dbus_get_name_owner(dbusmgr::dbus_manager& dbus_mgr, 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);
|
|
|
|
|
if(not reply) return false;
|
|
|
|
|
bool dbus_get_name_owner(dbusmgr::dbus_manager& dbus_mgr,
|
|
|
|
|
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);
|
|
|
|
|
if (not reply) return false;
|
|
|
|
|
|
|
|
|
|
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>();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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(
|
|
|
|
|
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);
|
|
|
|
|
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(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);
|
|
|
|
|
|
|
|
|
|
if(not reply) return false;
|
|
|
|
|
if (not reply) return false;
|
|
|
|
|
|
|
|
|
|
auto iter = reply.iter();
|
|
|
|
|
if(iter.is_array()){
|
|
|
|
|
string_multimap_for_each_stringify(iter, [&](const std::string& key, const std::string& val){
|
|
|
|
|
assign_metadata_value(meta, key, val);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else if(iter.is_primitive()){
|
|
|
|
|
if (iter.is_array()) {
|
|
|
|
|
iter.string_multimap_for_each_stringify(
|
|
|
|
|
[&](const std::string& key, const std::string& val) {
|
|
|
|
|
assign_metadata_value(meta, key, val);
|
|
|
|
|
});
|
|
|
|
|
} else if (iter.is_primitive()) {
|
|
|
|
|
assign_metadata_value(meta, prop, iter.get_stringified());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@ -165,8 +145,8 @@ bool dbus_get_player_property(dbusmgr::dbus_manager& dbus_mgr, metadata& meta, c
|
|
|
|
|
|
|
|
|
|
namespace dbusmgr {
|
|
|
|
|
bool dbus_manager::get_media_player_metadata(metadata& meta, std::string name) {
|
|
|
|
|
if(name == "") name = m_active_player;
|
|
|
|
|
if(name == "") return false;
|
|
|
|
|
if (name == "") name = m_active_player;
|
|
|
|
|
if (name == "") return false;
|
|
|
|
|
meta.clear();
|
|
|
|
|
dbus_get_player_property(*this, meta, name.c_str(), "Metadata");
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool dbus_manager::init(const std::string& requested_player)
|
|
|
|
|
{
|
|
|
|
|
if (m_inited)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
bool dbus_manager::init(const std::string& requested_player) {
|
|
|
|
|
if (m_inited) return true;
|
|
|
|
|
|
|
|
|
|
m_requested_player = "org.mpris.MediaPlayer2." + requested_player;
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
m_dbus_ldr.error_free(&m_error);
|
|
|
|
|
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();
|
|
|
|
|
connect_to_signals();
|
|
|
|
|
|
|
|
|
|
select_active_player();
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(main_metadata.mtx);
|
|
|
|
|
get_media_player_metadata(main_metadata.meta);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_inited = 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(m_name_owners.count(m_requested_player) > 0) {
|
|
|
|
|
if (m_name_owners.count(m_requested_player) > 0) {
|
|
|
|
|
m_active_player = m_requested_player;
|
|
|
|
|
std::cerr << "Selecting requested player: " << m_requested_player << "\n";
|
|
|
|
|
if(store_meta) get_media_player_metadata(*store_meta, m_active_player);
|
|
|
|
|
return true;
|
|
|
|
|
std::cerr << "Selecting requested player: " << m_requested_player
|
|
|
|
|
<< "\n";
|
|
|
|
|
get_media_player_metadata(meta, m_active_player);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Else, use any player that is currently playing..
|
|
|
|
|
for(const auto& entry : m_name_owners) {
|
|
|
|
|
const auto& name = std::get<0>(entry);
|
|
|
|
|
metadata meta;
|
|
|
|
|
get_media_player_metadata(meta, name);
|
|
|
|
|
if(meta.playing) {
|
|
|
|
|
m_active_player = name;
|
|
|
|
|
std::cerr << "Selecting fallback player: " << name << "\n";
|
|
|
|
|
if(store_meta) *store_meta = meta;
|
|
|
|
|
return true;
|
|
|
|
|
if (m_active_player.empty()) {
|
|
|
|
|
for (const auto& entry : m_name_owners) {
|
|
|
|
|
const auto& name = std::get<0>(entry);
|
|
|
|
|
get_media_player_metadata(meta, name);
|
|
|
|
|
if (meta.playing) {
|
|
|
|
|
m_active_player = name;
|
|
|
|
|
std::cerr << "Selecting fallback player: " << name << "\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No media players are active
|
|
|
|
|
std::cerr << "No active players\n";
|
|
|
|
|
m_active_player = "";
|
|
|
|
|
if(store_meta) store_meta->clear();
|
|
|
|
|
return false;
|
|
|
|
|
if (not m_active_player.empty()) {
|
|
|
|
|
if (m_active_player != old_active_player) {
|
|
|
|
|
onNewPlayer(meta);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
std::cerr << "No active players\n";
|
|
|
|
|
if (not old_active_player.empty()) {
|
|
|
|
|
onNoPlayer();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dbus_manager::deinit()
|
|
|
|
|
{
|
|
|
|
|
if (!m_inited)
|
|
|
|
|
return;
|
|
|
|
|
void dbus_manager::deinit() {
|
|
|
|
|
if (!m_inited) return;
|
|
|
|
|
|
|
|
|
|
// unreference system bus connection instead of closing it
|
|
|
|
|
if (m_dbus_conn) {
|
|
|
|
@ -255,18 +238,17 @@ void dbus_manager::deinit()
|
|
|
|
|
m_inited = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbus_manager::~dbus_manager()
|
|
|
|
|
{
|
|
|
|
|
deinit();
|
|
|
|
|
}
|
|
|
|
|
dbus_manager::~dbus_manager() { 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);
|
|
|
|
|
|
|
|
|
|
for(auto& sig : manager.m_signals) {
|
|
|
|
|
if(manager.m_dbus_ldr.message_is_signal(msg, sig.intf, sig.signal)){
|
|
|
|
|
for (auto& sig : manager.m_signals) {
|
|
|
|
|
if (manager.m_dbus_ldr.message_is_signal(msg, sig.intf, sig.signal)) {
|
|
|
|
|
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;
|
|
|
|
|
else
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
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 << "\tSource: " << source << "\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";
|
|
|
|
|
#endif
|
|
|
|
|
if (source != "org.mpris.MediaPlayer2.Player")
|
|
|
|
|
return false;
|
|
|
|
|
if (source != "org.mpris.MediaPlayer2.Player") return false;
|
|
|
|
|
|
|
|
|
|
if(m_active_player == "") {
|
|
|
|
|
select_active_player(&meta);
|
|
|
|
|
if (m_active_player == "") {
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool dbus_manager::handle_name_owner_changed(DBusMessage* msg, const char* sender) {
|
|
|
|
|
DBusMessageIter iter;
|
|
|
|
|
m_dbus_ldr.message_iter_init (msg, &iter);
|
|
|
|
|
bool dbus_manager::handle_name_owner_changed(DBusMessage* _msg,
|
|
|
|
|
const char* sender) {
|
|
|
|
|
std::vector<std::string> str;
|
|
|
|
|
const char *value = nullptr;
|
|
|
|
|
|
|
|
|
|
while (m_dbus_ldr.message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) {
|
|
|
|
|
m_dbus_ldr.message_iter_get_basic (&iter, &value);
|
|
|
|
|
str.push_back(value);
|
|
|
|
|
m_dbus_ldr.message_iter_next (&iter);
|
|
|
|
|
for (auto iter = DBusMessageIter_wrap(_msg, &m_dbus_ldr); iter;
|
|
|
|
|
iter.next()) {
|
|
|
|
|
str.push_back(iter.get_primitive<std::string>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// register new name
|
|
|
|
|
if (str.size() == 3
|
|
|
|
|
&& starts_with(str[0], "org.mpris.MediaPlayer2.")
|
|
|
|
|
&& !str[2].empty()
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
if (str.size() == 3 && starts_with(str[0], "org.mpris.MediaPlayer2.") &&
|
|
|
|
|
!str[2].empty()) {
|
|
|
|
|
m_name_owners[str[0]] = str[2];
|
|
|
|
|
if(str[0] == m_requested_player){
|
|
|
|
|
metadata tmp;
|
|
|
|
|
select_active_player(&tmp);
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(main_metadata.mtx);
|
|
|
|
|
main_metadata.meta = tmp;
|
|
|
|
|
main_metadata.ticker = {};
|
|
|
|
|
}
|
|
|
|
|
if (str[0] == m_requested_player) {
|
|
|
|
|
select_active_player();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// did a player quit?
|
|
|
|
|
if (str[2].empty()) {
|
|
|
|
|
if (str.size() == 3
|
|
|
|
|
&& str[0] == m_active_player
|
|
|
|
|
) {
|
|
|
|
|
metadata tmp;
|
|
|
|
|
if (str.size() == 3 && str[0] == m_active_player) {
|
|
|
|
|
m_name_owners.erase(str[0]);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dbus_manager::connect_to_signals()
|
|
|
|
|
{
|
|
|
|
|
void dbus_manager::connect_to_signals() {
|
|
|
|
|
for (auto kv : m_signals) {
|
|
|
|
|
auto signal = format_signal(kv);
|
|
|
|
|
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.message);
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dbus_manager::disconnect_from_signals()
|
|
|
|
|
{
|
|
|
|
|
m_dbus_ldr.connection_remove_filter(m_dbus_conn, filter_signals, reinterpret_cast<void*>(this));
|
|
|
|
|
void dbus_manager::disconnect_from_signals() {
|
|
|
|
|
m_dbus_ldr.connection_remove_filter(m_dbus_conn, filter_signals,
|
|
|
|
|
reinterpret_cast<void*>(this));
|
|
|
|
|
for (auto kv : m_signals) {
|
|
|
|
|
auto signal = format_signal(kv);
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
if(not reply) return false;
|
|
|
|
|
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);
|
|
|
|
|
if (not reply) return false;
|
|
|
|
|
|
|
|
|
|
auto iter = reply.iter();
|
|
|
|
|
|
|
|
|
|
if(not iter.is_array()) {
|
|
|
|
|
if (not iter.is_array()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
array_for_each<std::string>(iter, [&](std::string name){
|
|
|
|
|
if(!starts_with(name.c_str(), "org.mpris.MediaPlayer2.")) return;
|
|
|
|
|
iter.array_for_each_value<std::string>([&](std::string name) {
|
|
|
|
|
if (!starts_with(name.c_str(), "org.mpris.MediaPlayer2.")) return;
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dbus_manager::stop_thread()
|
|
|
|
|
{
|
|
|
|
|
void dbus_manager::stop_thread() {
|
|
|
|
|
m_quit = true;
|
|
|
|
|
if (m_thread.joinable())
|
|
|
|
|
m_thread.join();
|
|
|
|
|
if (m_thread.joinable()) m_thread.join();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dbus_manager::start_thread()
|
|
|
|
|
{
|
|
|
|
|
void dbus_manager::start_thread() {
|
|
|
|
|
stop_thread();
|
|
|
|
|
m_quit = false;
|
|
|
|
|
m_thread = std::thread(&dbus_manager::dbus_thread, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dbus_manager::dbus_thread()
|
|
|
|
|
{
|
|
|
|
|
void dbus_manager::dbus_thread() {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|