From 72b86b4371513dbfa433af86acba176e207d47d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Kr=C3=A4mer?= <24323470+larskraemer@users.noreply.github.com> Date: Wed, 1 Jul 2020 13:19:06 +0200 Subject: [PATCH] Fix some weird behaviour with non-spotify media players Add DBusMessage_wrap to wrap/hide some dbus_message_* calls --- src/dbus.cpp | 252 +++++++++++++++++++++++++++++++----------------- src/dbus_info.h | 2 + 2 files changed, 166 insertions(+), 88 deletions(-) diff --git a/src/dbus.cpp b/src/dbus.cpp index 30c9d8f9..849fe804 100644 --- a/src/dbus.cpp +++ b/src/dbus.cpp @@ -52,9 +52,14 @@ public: DBusMessageIter_wrap(DBusMessage* msg, libdbus_loader* loader) { m_DBus = loader; - 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); + 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) @@ -253,24 +258,114 @@ void string_multimap_for_each_stringify(DBusMessageIter_wrap iter, T action) { }); } +class DBusMessage_wrap { +public: + DBusMessage_wrap(DBusMessage* msg, libdbus_loader* ldr, bool owning = false) + : m_owning(owning), m_msg(msg), m_DBus(ldr) + {} + + ~DBusMessage_wrap(){ + free_if_owning(); + } + + DBusMessage_wrap(const DBusMessage_wrap&) = delete; + DBusMessage_wrap(DBusMessage_wrap&&) = default; + + operator bool() const { + return m_msg != nullptr; + } + + template + DBusMessage_wrap& argument(T arg) { + if(not m_msg) return *this; + if(not m_DBus->message_append_args( + m_msg, + dbus_type_identifier_v, + &arg, + DBUS_TYPE_INVALID + )){ + free_if_owning(); + } + return *this; + } + + DBusMessage_wrap send_with_reply_and_block(DBusConnection* conn) { + 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, + DBUS_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() { + return DBusMessageIter_wrap(m_msg, m_DBus); + } + + static 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); + } +private: + void free_if_owning() { + if(m_msg and m_owning) m_DBus->message_unref(m_msg); + m_msg = nullptr; + } + bool m_owning; + DBusMessage* m_msg; + libdbus_loader* m_DBus; + std::vector m_args; +}; + +template<> +DBusMessage_wrap& DBusMessage_wrap::argument(const std::string& str) +{ + return argument(str.c_str()); +} template 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"){ meta.title = value; + meta.got_song_data = true; } else if(key == "xesam:artist") { - if(meta.artists.empty()) meta.artists = value; - else meta.artists += ", " + value; + meta.artists = value; + meta.got_song_data = true; } else if(key == "xesam:album") { meta.album = value; + meta.got_song_data = true; } else if(key == "mpris:artUrl"){ meta.artUrl = value; + meta.got_song_data = true; } } @@ -311,99 +406,76 @@ static void parse_mpris_properties(libdbus_loader& dbus, DBusMessage *msg, std:: 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()){ + val = str; + } + 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"){ - assign_metadata_value(meta, key, it.get_stringified()); + auto val = it.get_stringified(); + std::cerr << "\tPlaybackStatus:\n"; + std::cerr << "\t\t" << key << " -> " << val << "\n"; + assign_metadata_value(meta, key, val); } }); 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& dbus = dbus_mgr.dbus(); - DBusError error; - - DBusMessage * dbus_reply = nullptr; - DBusMessage * dbus_msg = nullptr; - - // dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:"org.mpris.MediaPlayer2.spotify" - if (nullptr == (dbus_msg = dbus.message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetNameOwner"))) { - std::cerr << "MANGOHUD: " << __func__ << ": unable to allocate memory for dbus message\n"; - return false; - } - - if (!dbus.message_append_args (dbus_msg, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) { - dbus.message_unref(dbus_msg); - std::cerr << "MANGOHUD: " << __func__ << ": dbus_message_append_args failed\n"; - return false; - } - - dbus.error_init(&error); - if (nullptr == (dbus_reply = dbus.connection_send_with_reply_and_block(dbus_mgr.get_conn(), dbus_msg, DBUS_TIMEOUT, &error))) { - dbus.message_unref(dbus_msg); - std::cerr << "MANGOHUD: " << __func__ << ": "<< error.message << "\n"; - dbus.error_free(&error); - return false; - } - - const char* val = nullptr; - DBusMessageIter iter; - dbus.message_iter_init (dbus_reply, &iter); - - if (dbus.message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) - return false; - - dbus.message_iter_get_basic(&iter, &val); - if (val) - name_owner = val; - - dbus.message_unref(dbus_msg); - dbus.message_unref(dbus_reply); - dbus.error_free(&error); + 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()); + if(not reply) return false; + + auto iter = reply.iter(); + if(not iter.is_string()) return false; + name_owner = iter.get_primitive(); return true; } bool dbus_get_player_property(dbusmgr::dbus_manager& dbus_mgr, metadata& meta, const char * dest, const char * prop) { - auto& dbus = dbus_mgr.dbus(); - DBusError error; - - DBusMessage * dbus_reply = nullptr; - DBusMessage * dbus_msg = nullptr; - - // dbus-send --print-reply --session --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata' - if (nullptr == (dbus_msg = dbus.message_new_method_call(dest, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get"))) { - std::cerr << "MANGOHUD: unable to allocate memory for dbus message" << std::endl; - return false; - } - - static const char *v_STRINGS[] = { - "org.mpris.MediaPlayer2.Player", - }; - - if (!dbus.message_append_args (dbus_msg, DBUS_TYPE_STRING, &v_STRINGS[0], DBUS_TYPE_STRING, &prop, DBUS_TYPE_INVALID)) { - std::cerr << "MANGOHUD: dbus_message_append_args failed" << std::endl; - dbus.message_unref(dbus_msg); - return false; - } - - dbus.error_init(&error); - if (nullptr == (dbus_reply = dbus.connection_send_with_reply_and_block(dbus_mgr.get_conn(), dbus_msg, DBUS_TIMEOUT, &error))) { - dbus.message_unref(dbus_msg); - std::cerr << "MANGOHUD: " << error.message << std::endl; - dbus.error_free(&error); - return false; - } - - auto iter = DBusMessageIter_wrap(dbus_reply, &dbus); + 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()); + + 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); @@ -413,15 +485,8 @@ bool dbus_get_player_property(dbusmgr::dbus_manager& dbus_mgr, metadata& meta, c assign_metadata_value(meta, prop, iter.get_stringified()); } else { - dbus.message_unref(dbus_msg); - dbus.message_unref(dbus_reply); - dbus.error_free(&error); return false; } - - dbus.message_unref(dbus_msg); - dbus.message_unref(dbus_reply); - dbus.error_free(&error); return true; } @@ -554,7 +619,13 @@ bool dbus_manager::handle_properties_changed(DBusMessage* msg, const char* sende } if (m_name_owners[m_active_player] == sender) { std::lock_guard lck(main_metadata.mtx); - main_metadata.meta = meta; + if(meta.got_song_data){ + main_metadata.meta = meta; + main_metadata.meta.playing = true; + } + if(meta.got_playback_data){ + main_metadata.meta.playing = meta.playing; + } } return true; } @@ -665,7 +736,12 @@ bool dbus_manager::dbus_list_name_to_owner() } auto iter = DBusMessageIter_wrap(dbus_reply, &m_dbus_ldr); - if(not iter.is_array()) return false; + if(not iter.is_array()) { + m_dbus_ldr.message_unref(dbus_msg); + m_dbus_ldr.message_unref(dbus_reply); + m_dbus_ldr.error_free(&error); + return false; + } array_for_each(iter, [&](std::string name){ if(!starts_with(name.c_str(), "org.mpris.MediaPlayer2.")) return; if(dbus_get_name_owner(dbus_mgr, owner, name.c_str())){ diff --git a/src/dbus_info.h b/src/dbus_info.h index dd958cbe..d0963631 100644 --- a/src/dbus_info.h +++ b/src/dbus_info.h @@ -35,6 +35,8 @@ struct metadata { } ticker; bool valid = false; + bool got_song_data = false; + bool got_playback_data = false; void clear() {