From b874058ae81e683cf8468c847d1bb1e9686de94a Mon Sep 17 00:00:00 2001 From: "Igor V. Kovalenko" Date: Sun, 14 Mar 2021 14:15:40 +0300 Subject: [PATCH] card: use JSON with pulseaudio messaging API Part-of: --- configure.ac | 2 +- src/cardwidget.cc | 2 +- src/mainwindow.cc | 4 -- src/pavucontrol.cc | 142 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 116 insertions(+), 34 deletions(-) diff --git a/configure.ac b/configure.ac index 2ae549f..1079361 100644 --- a/configure.ac +++ b/configure.ac @@ -41,7 +41,7 @@ AC_TYPE_SIGNAL AC_HEADER_STDC AX_CXX_COMPILE_STDCXX_11 -PKG_CHECK_MODULES(GUILIBS, [ gtkmm-3.0 >= 3.22 sigc++-2.0 libcanberra-gtk3 >= 0.16 ]) +PKG_CHECK_MODULES(GUILIBS, [ gtkmm-3.0 >= 3.22 sigc++-2.0 libcanberra-gtk3 >= 0.16 json-glib-1.0 ]) AC_SUBST(GUILIBS_CFLAGS) AC_SUBST(GUILIBS_LIBS) diff --git a/src/cardwidget.cc b/src/cardwidget.cc index 089768e..b4fe378 100644 --- a/src/cardwidget.cc +++ b/src/cardwidget.cc @@ -137,7 +137,7 @@ void CardWidget::onCodecChange() { pa_operation* o; Glib::ustring codec_id = row[codecModel.name]; - std::string codec_message = "{" + std::string(codec_id) + "}"; + std::string codec_message = "\"" + std::string(codec_id) + "\""; if (!(o = pa_context_send_message_to_object(get_context(), card_bluez_message_handler_path(pulse_card_name).c_str(), "switch-codec", codec_message.c_str(), NULL, NULL))) { diff --git a/src/mainwindow.cc b/src/mainwindow.cc index 34013e7..ea290bd 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -35,10 +35,6 @@ #include "i18n.h" -#if defined(HAVE_PULSE_MESSAGING_API) -#include -#endif - /* Used for profile sorting */ struct profile_prio_compare { bool operator() (const pa_card_profile_info2& lhs, const pa_card_profile_info2& rhs) const { diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc index e735622..3f5c218 100644 --- a/src/pavucontrol.cc +++ b/src/pavucontrol.cc @@ -26,7 +26,7 @@ #include #include #ifdef HAVE_PULSE_MESSAGING_API -#include +#include #endif #include @@ -91,38 +91,70 @@ static void context_bluetooth_card_codec_list_cb(pa_context *c, int success, cha if (!success) return; - void *state = NULL; - char *codec_list; - char *handler_struct; - int err; + int err = 0; - if (pa_message_params_read_raw(response, &codec_list, &state) <= 0) { - show_error(_("list-codecs message response could not be parsed correctly")); + GError *gerror = NULL; + JsonParser *parser = json_parser_new(); + + if (!json_parser_load_from_data(parser, response, strlen(response), &gerror)) { + g_debug(_("could not read JSON from list-codecs message response: %s"), gerror->message); + g_error_free(gerror); + g_object_unref(parser); return; } + JsonNode *root = json_parser_get_root(parser); + + if (!root || JSON_NODE_TYPE(root) != JSON_NODE_ARRAY) { + g_debug(_("list-codecs message response is not a JSON array")); + g_object_unref(parser); + return; + } + + JsonArray *array = json_node_get_array(root); + std::unordered_map codecs; - state = NULL; - while ((err = pa_message_params_read_raw(codec_list, &handler_struct, &state)) > 0) { - void *state2 = NULL; + for (guint i = 0; i < json_array_get_length(array); ++i) { const char *path; const char *description; + JsonNode *v; - if (pa_message_params_read_string(handler_struct, &path, &state2) <= 0) { + JsonObject *object = json_array_get_object_element(array, i); + if (!object) { err = -1; break; } - if (pa_message_params_read_string(handler_struct, &description, &state2) <= 0) { + + v = json_object_get_member(object, "name"); + if (!v) { err = -1; break; } + path = json_node_get_string(v); + if (!path) { + err = -1; + break; + } + + v = json_object_get_member(object, "description"); + if (!v) { + err = -1; + break; + } + + description = json_node_get_string(v); + if (!description) + description = ""; + codecs[path] = description; } + g_object_unref(parser); + if (err < 0) { - show_error(_("list-codecs message response could not be parsed correctly")); + g_debug(_("list-codecs message response could not be parsed correctly")); codecs.clear(); return; } @@ -136,15 +168,37 @@ static void context_bluetooth_card_active_codec_cb(pa_context *c, int success, c if (!success) return; - void *state = NULL; const char *name; + GError *gerror = NULL; - if (pa_message_params_read_string(response, &name, &state) <= 0) { - show_error(_("get-codec message response could not be parsed correctly")); + JsonParser *parser = json_parser_new(); + + if (!json_parser_load_from_data(parser, response, strlen(response), &gerror)) { + g_debug(_("could not read JSON from get-codec message response: %s"), gerror->message); + g_error_free(gerror); + g_object_unref(parser); + return; + } + + JsonNode *root = json_parser_get_root(parser); + + if (!root || JSON_NODE_TYPE(root) != JSON_NODE_VALUE) { + g_debug(_("get-codec message response is not a JSON value")); + g_object_unref(parser); + return; + } + + name = json_node_get_string(root); + + if (!name) { + g_debug(_("could not get codec name from get-codec message response")); + g_object_unref(parser); return; } u->first->setActiveCodec(u->second, name); + + g_object_unref(parser); } template void send_message(pa_context *c, const char *target, const char *request, pa_context_string_cb_t cb, const U& u) @@ -167,38 +221,70 @@ static void context_message_handlers_cb(pa_context *c, int success, char *respon if (!success) return; - void *state = NULL; - char *handler_list; - char *handler_struct; - int err; + int err = 0; - if (pa_message_params_read_raw(response, &handler_list, &state) <= 0) { - show_error(_("list-handlers message response could not be parsed correctly")); + GError *gerror = NULL; + JsonParser *parser = json_parser_new(); + + if (!json_parser_load_from_data(parser, response, strlen(response), &gerror)) { + g_debug(_("could not read JSON from list-handlers message response: %s"), gerror->message); + g_error_free(gerror); + g_object_unref(parser); return; } + JsonNode *root = json_parser_get_root(parser); + + if (!root || JSON_NODE_TYPE(root) != JSON_NODE_ARRAY) { + g_debug(_("list-handlers message response is not a JSON array")); + g_object_unref(parser); + return; + } + + JsonArray *array = json_node_get_array(root); + std::unordered_map message_handler_map; - state = NULL; - while ((err = pa_message_params_read_raw(handler_list, &handler_struct, &state)) > 0) { - void *state2 = NULL; + for (guint i = 0; i < json_array_get_length(array); ++i) { const char *path; const char *description; + JsonNode *v; - if (pa_message_params_read_string(handler_struct, &path, &state2) <= 0) { + JsonObject *object = json_array_get_object_element(array, i); + if (!object) { err = -1; break; } - if (pa_message_params_read_string(handler_struct, &description, &state2) <= 0) { + + v = json_object_get_member(object, "name"); + if (!v) { err = -1; break; } + path = json_node_get_string(v); + if (!path) { + err = -1; + break; + } + + v = json_object_get_member(object, "description"); + if (!v) { + err = -1; + break; + } + + description = json_node_get_string(v); + if (!description) + description = ""; + message_handler_map[path] = description; } + g_object_unref(parser); + if (err < 0) { - show_error(_("list-handlers message response could not be parsed correctly")); + g_debug(_("list-handlers message response could not be parsed correctly")); message_handler_map.clear(); return; }