153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2009 Tanu Kaskinen 553a5a1b3Sopenharmony_ci 653a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 753a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 853a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 953a5a1b3Sopenharmony_ci or (at your option) any later version. 1053a5a1b3Sopenharmony_ci 1153a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1253a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1353a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1453a5a1b3Sopenharmony_ci General Public License for more details. 1553a5a1b3Sopenharmony_ci 1653a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1753a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1853a5a1b3Sopenharmony_ci***/ 1953a5a1b3Sopenharmony_ci 2053a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2153a5a1b3Sopenharmony_ci#include <config.h> 2253a5a1b3Sopenharmony_ci#endif 2353a5a1b3Sopenharmony_ci 2453a5a1b3Sopenharmony_ci#include <dbus/dbus.h> 2553a5a1b3Sopenharmony_ci 2653a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 2753a5a1b3Sopenharmony_ci#include <pulsecore/dbus-util.h> 2853a5a1b3Sopenharmony_ci#include <pulsecore/protocol-dbus.h> 2953a5a1b3Sopenharmony_ci 3053a5a1b3Sopenharmony_ci#include "iface-card-profile.h" 3153a5a1b3Sopenharmony_ci 3253a5a1b3Sopenharmony_ci#include "iface-card.h" 3353a5a1b3Sopenharmony_ci 3453a5a1b3Sopenharmony_ci#define OBJECT_NAME "card" 3553a5a1b3Sopenharmony_ci 3653a5a1b3Sopenharmony_cistatic void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); 3753a5a1b3Sopenharmony_cistatic void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); 3853a5a1b3Sopenharmony_cistatic void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata); 3953a5a1b3Sopenharmony_cistatic void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata); 4053a5a1b3Sopenharmony_cistatic void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata); 4153a5a1b3Sopenharmony_cistatic void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata); 4253a5a1b3Sopenharmony_cistatic void handle_get_profiles(DBusConnection *conn, DBusMessage *msg, void *userdata); 4353a5a1b3Sopenharmony_cistatic void handle_get_active_profile(DBusConnection *conn, DBusMessage *msg, void *userdata); 4453a5a1b3Sopenharmony_cistatic void handle_set_active_profile(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); 4553a5a1b3Sopenharmony_cistatic void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); 4653a5a1b3Sopenharmony_ci 4753a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); 4853a5a1b3Sopenharmony_ci 4953a5a1b3Sopenharmony_cistatic void handle_get_profile_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); 5053a5a1b3Sopenharmony_ci 5153a5a1b3Sopenharmony_cistruct pa_dbusiface_card { 5253a5a1b3Sopenharmony_ci pa_dbusiface_core *core; 5353a5a1b3Sopenharmony_ci 5453a5a1b3Sopenharmony_ci pa_card *card; 5553a5a1b3Sopenharmony_ci char *path; 5653a5a1b3Sopenharmony_ci pa_hashmap *profiles; 5753a5a1b3Sopenharmony_ci uint32_t next_profile_index; 5853a5a1b3Sopenharmony_ci pa_card_profile *active_profile; 5953a5a1b3Sopenharmony_ci pa_proplist *proplist; 6053a5a1b3Sopenharmony_ci 6153a5a1b3Sopenharmony_ci pa_hook_slot *card_profile_added_slot; 6253a5a1b3Sopenharmony_ci pa_hook_slot *card_profile_changed_slot; 6353a5a1b3Sopenharmony_ci pa_hook_slot *card_profile_available_slot; 6453a5a1b3Sopenharmony_ci 6553a5a1b3Sopenharmony_ci pa_dbus_protocol *dbus_protocol; 6653a5a1b3Sopenharmony_ci}; 6753a5a1b3Sopenharmony_ci 6853a5a1b3Sopenharmony_cienum property_handler_index { 6953a5a1b3Sopenharmony_ci PROPERTY_HANDLER_INDEX, 7053a5a1b3Sopenharmony_ci PROPERTY_HANDLER_NAME, 7153a5a1b3Sopenharmony_ci PROPERTY_HANDLER_DRIVER, 7253a5a1b3Sopenharmony_ci PROPERTY_HANDLER_OWNER_MODULE, 7353a5a1b3Sopenharmony_ci PROPERTY_HANDLER_SINKS, 7453a5a1b3Sopenharmony_ci PROPERTY_HANDLER_SOURCES, 7553a5a1b3Sopenharmony_ci PROPERTY_HANDLER_PROFILES, 7653a5a1b3Sopenharmony_ci PROPERTY_HANDLER_ACTIVE_PROFILE, 7753a5a1b3Sopenharmony_ci PROPERTY_HANDLER_PROPERTY_LIST, 7853a5a1b3Sopenharmony_ci PROPERTY_HANDLER_MAX 7953a5a1b3Sopenharmony_ci}; 8053a5a1b3Sopenharmony_ci 8153a5a1b3Sopenharmony_cistatic pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { 8253a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, 8353a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, 8453a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_DRIVER] = { .property_name = "Driver", .type = "s", .get_cb = handle_get_driver, .set_cb = NULL }, 8553a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_OWNER_MODULE] = { .property_name = "OwnerModule", .type = "o", .get_cb = handle_get_owner_module, .set_cb = NULL }, 8653a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_SINKS] = { .property_name = "Sinks", .type = "ao", .get_cb = handle_get_sinks, .set_cb = NULL }, 8753a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_SOURCES] = { .property_name = "Sources", .type = "ao", .get_cb = handle_get_sources, .set_cb = NULL }, 8853a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_PROFILES] = { .property_name = "Profiles", .type = "ao", .get_cb = handle_get_profiles, .set_cb = NULL }, 8953a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_ACTIVE_PROFILE] = { .property_name = "ActiveProfile", .type = "o", .get_cb = handle_get_active_profile, .set_cb = handle_set_active_profile }, 9053a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } 9153a5a1b3Sopenharmony_ci}; 9253a5a1b3Sopenharmony_ci 9353a5a1b3Sopenharmony_cienum method_handler_index { 9453a5a1b3Sopenharmony_ci METHOD_HANDLER_GET_PROFILE_BY_NAME, 9553a5a1b3Sopenharmony_ci METHOD_HANDLER_MAX 9653a5a1b3Sopenharmony_ci}; 9753a5a1b3Sopenharmony_ci 9853a5a1b3Sopenharmony_cistatic pa_dbus_arg_info get_profile_by_name_args[] = { { "name", "s", "in" }, { "profile", "o", "out" } }; 9953a5a1b3Sopenharmony_ci 10053a5a1b3Sopenharmony_cistatic pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { 10153a5a1b3Sopenharmony_ci [METHOD_HANDLER_GET_PROFILE_BY_NAME] = { 10253a5a1b3Sopenharmony_ci .method_name = "GetProfileByName", 10353a5a1b3Sopenharmony_ci .arguments = get_profile_by_name_args, 10453a5a1b3Sopenharmony_ci .n_arguments = sizeof(get_profile_by_name_args) / sizeof(pa_dbus_arg_info), 10553a5a1b3Sopenharmony_ci .receive_cb = handle_get_profile_by_name } 10653a5a1b3Sopenharmony_ci}; 10753a5a1b3Sopenharmony_ci 10853a5a1b3Sopenharmony_cienum signal_index { 10953a5a1b3Sopenharmony_ci SIGNAL_ACTIVE_PROFILE_UPDATED, 11053a5a1b3Sopenharmony_ci SIGNAL_NEW_PROFILE, 11153a5a1b3Sopenharmony_ci SIGNAL_PROFILE_AVAILABLE_CHANGED, 11253a5a1b3Sopenharmony_ci SIGNAL_PROPERTY_LIST_UPDATED, 11353a5a1b3Sopenharmony_ci SIGNAL_MAX 11453a5a1b3Sopenharmony_ci}; 11553a5a1b3Sopenharmony_ci 11653a5a1b3Sopenharmony_cistatic pa_dbus_arg_info active_profile_updated_args[] = { { "profile", "o", NULL } }; 11753a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_profile_args[] = { { "profile", "o", NULL } }; 11853a5a1b3Sopenharmony_cistatic pa_dbus_arg_info profile_available_changed_args[] = { { "profile", "o", NULL }, 11953a5a1b3Sopenharmony_ci { "available", "b", NULL } }; 12053a5a1b3Sopenharmony_cistatic pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; 12153a5a1b3Sopenharmony_ci 12253a5a1b3Sopenharmony_cistatic pa_dbus_signal_info signals[SIGNAL_MAX] = { 12353a5a1b3Sopenharmony_ci [SIGNAL_ACTIVE_PROFILE_UPDATED] = { .name = "ActiveProfileUpdated", .arguments = active_profile_updated_args, .n_arguments = 1 }, 12453a5a1b3Sopenharmony_ci [SIGNAL_NEW_PROFILE] = { .name = "NewProfile", .arguments = new_profile_args, .n_arguments = 1 }, 12553a5a1b3Sopenharmony_ci [SIGNAL_PROFILE_AVAILABLE_CHANGED] = { .name = "ProfileAvailableChanged", .arguments = profile_available_changed_args, .n_arguments = 2 }, 12653a5a1b3Sopenharmony_ci [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 } 12753a5a1b3Sopenharmony_ci}; 12853a5a1b3Sopenharmony_ci 12953a5a1b3Sopenharmony_cistatic pa_dbus_interface_info card_interface_info = { 13053a5a1b3Sopenharmony_ci .name = PA_DBUSIFACE_CARD_INTERFACE, 13153a5a1b3Sopenharmony_ci .method_handlers = method_handlers, 13253a5a1b3Sopenharmony_ci .n_method_handlers = METHOD_HANDLER_MAX, 13353a5a1b3Sopenharmony_ci .property_handlers = property_handlers, 13453a5a1b3Sopenharmony_ci .n_property_handlers = PROPERTY_HANDLER_MAX, 13553a5a1b3Sopenharmony_ci .get_all_properties_cb = handle_get_all, 13653a5a1b3Sopenharmony_ci .signals = signals, 13753a5a1b3Sopenharmony_ci .n_signals = SIGNAL_MAX 13853a5a1b3Sopenharmony_ci}; 13953a5a1b3Sopenharmony_ci 14053a5a1b3Sopenharmony_cistatic void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { 14153a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 14253a5a1b3Sopenharmony_ci dbus_uint32_t idx; 14353a5a1b3Sopenharmony_ci 14453a5a1b3Sopenharmony_ci pa_assert(conn); 14553a5a1b3Sopenharmony_ci pa_assert(msg); 14653a5a1b3Sopenharmony_ci pa_assert(c); 14753a5a1b3Sopenharmony_ci 14853a5a1b3Sopenharmony_ci idx = c->card->index; 14953a5a1b3Sopenharmony_ci 15053a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); 15153a5a1b3Sopenharmony_ci} 15253a5a1b3Sopenharmony_ci 15353a5a1b3Sopenharmony_cistatic void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { 15453a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 15553a5a1b3Sopenharmony_ci 15653a5a1b3Sopenharmony_ci pa_assert(conn); 15753a5a1b3Sopenharmony_ci pa_assert(msg); 15853a5a1b3Sopenharmony_ci pa_assert(c); 15953a5a1b3Sopenharmony_ci 16053a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &c->card->name); 16153a5a1b3Sopenharmony_ci} 16253a5a1b3Sopenharmony_ci 16353a5a1b3Sopenharmony_cistatic void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) { 16453a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 16553a5a1b3Sopenharmony_ci 16653a5a1b3Sopenharmony_ci pa_assert(conn); 16753a5a1b3Sopenharmony_ci pa_assert(msg); 16853a5a1b3Sopenharmony_ci pa_assert(c); 16953a5a1b3Sopenharmony_ci 17053a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &c->card->driver); 17153a5a1b3Sopenharmony_ci} 17253a5a1b3Sopenharmony_ci 17353a5a1b3Sopenharmony_cistatic void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) { 17453a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 17553a5a1b3Sopenharmony_ci const char *owner_module; 17653a5a1b3Sopenharmony_ci 17753a5a1b3Sopenharmony_ci pa_assert(conn); 17853a5a1b3Sopenharmony_ci pa_assert(msg); 17953a5a1b3Sopenharmony_ci pa_assert(c); 18053a5a1b3Sopenharmony_ci 18153a5a1b3Sopenharmony_ci if (!c->card->module) { 18253a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Card %s doesn't have an owner module.", c->card->name); 18353a5a1b3Sopenharmony_ci return; 18453a5a1b3Sopenharmony_ci } 18553a5a1b3Sopenharmony_ci 18653a5a1b3Sopenharmony_ci owner_module = pa_dbusiface_core_get_module_path(c->core, c->card->module); 18753a5a1b3Sopenharmony_ci 18853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &owner_module); 18953a5a1b3Sopenharmony_ci} 19053a5a1b3Sopenharmony_ci 19153a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */ 19253a5a1b3Sopenharmony_cistatic const char **get_sinks(pa_dbusiface_card *c, unsigned *n) { 19353a5a1b3Sopenharmony_ci const char **sinks = NULL; 19453a5a1b3Sopenharmony_ci unsigned i = 0; 19553a5a1b3Sopenharmony_ci uint32_t idx = 0; 19653a5a1b3Sopenharmony_ci pa_sink *sink = NULL; 19753a5a1b3Sopenharmony_ci 19853a5a1b3Sopenharmony_ci pa_assert(c); 19953a5a1b3Sopenharmony_ci pa_assert(n); 20053a5a1b3Sopenharmony_ci 20153a5a1b3Sopenharmony_ci *n = pa_idxset_size(c->card->sinks); 20253a5a1b3Sopenharmony_ci 20353a5a1b3Sopenharmony_ci if (*n == 0) 20453a5a1b3Sopenharmony_ci return NULL; 20553a5a1b3Sopenharmony_ci 20653a5a1b3Sopenharmony_ci sinks = pa_xnew(const char *, *n); 20753a5a1b3Sopenharmony_ci 20853a5a1b3Sopenharmony_ci PA_IDXSET_FOREACH(sink, c->card->sinks, idx) { 20953a5a1b3Sopenharmony_ci sinks[i] = pa_dbusiface_core_get_sink_path(c->core, sink); 21053a5a1b3Sopenharmony_ci ++i; 21153a5a1b3Sopenharmony_ci } 21253a5a1b3Sopenharmony_ci 21353a5a1b3Sopenharmony_ci return sinks; 21453a5a1b3Sopenharmony_ci} 21553a5a1b3Sopenharmony_ci 21653a5a1b3Sopenharmony_cistatic void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata) { 21753a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 21853a5a1b3Sopenharmony_ci const char **sinks; 21953a5a1b3Sopenharmony_ci unsigned n_sinks; 22053a5a1b3Sopenharmony_ci 22153a5a1b3Sopenharmony_ci pa_assert(conn); 22253a5a1b3Sopenharmony_ci pa_assert(msg); 22353a5a1b3Sopenharmony_ci pa_assert(c); 22453a5a1b3Sopenharmony_ci 22553a5a1b3Sopenharmony_ci sinks = get_sinks(c, &n_sinks); 22653a5a1b3Sopenharmony_ci 22753a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, sinks, n_sinks); 22853a5a1b3Sopenharmony_ci 22953a5a1b3Sopenharmony_ci pa_xfree(sinks); 23053a5a1b3Sopenharmony_ci} 23153a5a1b3Sopenharmony_ci 23253a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */ 23353a5a1b3Sopenharmony_cistatic const char **get_sources(pa_dbusiface_card *c, unsigned *n) { 23453a5a1b3Sopenharmony_ci const char **sources = NULL; 23553a5a1b3Sopenharmony_ci unsigned i = 0; 23653a5a1b3Sopenharmony_ci uint32_t idx = 0; 23753a5a1b3Sopenharmony_ci pa_source *source = NULL; 23853a5a1b3Sopenharmony_ci 23953a5a1b3Sopenharmony_ci pa_assert(c); 24053a5a1b3Sopenharmony_ci pa_assert(n); 24153a5a1b3Sopenharmony_ci 24253a5a1b3Sopenharmony_ci *n = pa_idxset_size(c->card->sources); 24353a5a1b3Sopenharmony_ci 24453a5a1b3Sopenharmony_ci if (*n == 0) 24553a5a1b3Sopenharmony_ci return NULL; 24653a5a1b3Sopenharmony_ci 24753a5a1b3Sopenharmony_ci sources = pa_xnew(const char *, *n); 24853a5a1b3Sopenharmony_ci 24953a5a1b3Sopenharmony_ci PA_IDXSET_FOREACH(source, c->card->sources, idx) { 25053a5a1b3Sopenharmony_ci sources[i] = pa_dbusiface_core_get_source_path(c->core, source); 25153a5a1b3Sopenharmony_ci ++i; 25253a5a1b3Sopenharmony_ci } 25353a5a1b3Sopenharmony_ci 25453a5a1b3Sopenharmony_ci return sources; 25553a5a1b3Sopenharmony_ci} 25653a5a1b3Sopenharmony_ci 25753a5a1b3Sopenharmony_cistatic void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata) { 25853a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 25953a5a1b3Sopenharmony_ci const char **sources; 26053a5a1b3Sopenharmony_ci unsigned n_sources; 26153a5a1b3Sopenharmony_ci 26253a5a1b3Sopenharmony_ci pa_assert(conn); 26353a5a1b3Sopenharmony_ci pa_assert(msg); 26453a5a1b3Sopenharmony_ci pa_assert(c); 26553a5a1b3Sopenharmony_ci 26653a5a1b3Sopenharmony_ci sources = get_sources(c, &n_sources); 26753a5a1b3Sopenharmony_ci 26853a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, sources, n_sources); 26953a5a1b3Sopenharmony_ci 27053a5a1b3Sopenharmony_ci pa_xfree(sources); 27153a5a1b3Sopenharmony_ci} 27253a5a1b3Sopenharmony_ci 27353a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */ 27453a5a1b3Sopenharmony_cistatic const char **get_profiles(pa_dbusiface_card *c, unsigned *n) { 27553a5a1b3Sopenharmony_ci const char **profiles; 27653a5a1b3Sopenharmony_ci unsigned i = 0; 27753a5a1b3Sopenharmony_ci void *state = NULL; 27853a5a1b3Sopenharmony_ci pa_dbusiface_card_profile *profile; 27953a5a1b3Sopenharmony_ci 28053a5a1b3Sopenharmony_ci pa_assert(c); 28153a5a1b3Sopenharmony_ci pa_assert(n); 28253a5a1b3Sopenharmony_ci 28353a5a1b3Sopenharmony_ci *n = pa_hashmap_size(c->profiles); 28453a5a1b3Sopenharmony_ci 28553a5a1b3Sopenharmony_ci if (*n == 0) 28653a5a1b3Sopenharmony_ci return NULL; 28753a5a1b3Sopenharmony_ci 28853a5a1b3Sopenharmony_ci profiles = pa_xnew(const char *, *n); 28953a5a1b3Sopenharmony_ci 29053a5a1b3Sopenharmony_ci PA_HASHMAP_FOREACH(profile, c->profiles, state) 29153a5a1b3Sopenharmony_ci profiles[i++] = pa_dbusiface_card_profile_get_path(profile); 29253a5a1b3Sopenharmony_ci 29353a5a1b3Sopenharmony_ci return profiles; 29453a5a1b3Sopenharmony_ci} 29553a5a1b3Sopenharmony_ci 29653a5a1b3Sopenharmony_cistatic void handle_get_profiles(DBusConnection *conn, DBusMessage *msg, void *userdata) { 29753a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 29853a5a1b3Sopenharmony_ci const char **profiles; 29953a5a1b3Sopenharmony_ci unsigned n_profiles; 30053a5a1b3Sopenharmony_ci 30153a5a1b3Sopenharmony_ci pa_assert(conn); 30253a5a1b3Sopenharmony_ci pa_assert(msg); 30353a5a1b3Sopenharmony_ci pa_assert(c); 30453a5a1b3Sopenharmony_ci 30553a5a1b3Sopenharmony_ci profiles = get_profiles(c, &n_profiles); 30653a5a1b3Sopenharmony_ci 30753a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, profiles, n_profiles); 30853a5a1b3Sopenharmony_ci 30953a5a1b3Sopenharmony_ci pa_xfree(profiles); 31053a5a1b3Sopenharmony_ci} 31153a5a1b3Sopenharmony_ci 31253a5a1b3Sopenharmony_cistatic void handle_get_active_profile(DBusConnection *conn, DBusMessage *msg, void *userdata) { 31353a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 31453a5a1b3Sopenharmony_ci const char *active_profile; 31553a5a1b3Sopenharmony_ci 31653a5a1b3Sopenharmony_ci pa_assert(conn); 31753a5a1b3Sopenharmony_ci pa_assert(msg); 31853a5a1b3Sopenharmony_ci pa_assert(c); 31953a5a1b3Sopenharmony_ci 32053a5a1b3Sopenharmony_ci active_profile = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name)); 32153a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &active_profile); 32253a5a1b3Sopenharmony_ci} 32353a5a1b3Sopenharmony_ci 32453a5a1b3Sopenharmony_cistatic void handle_set_active_profile(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { 32553a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 32653a5a1b3Sopenharmony_ci const char *new_active_path; 32753a5a1b3Sopenharmony_ci pa_dbusiface_card_profile *profile; 32853a5a1b3Sopenharmony_ci void *state; 32953a5a1b3Sopenharmony_ci pa_dbusiface_card_profile *new_active = NULL; 33053a5a1b3Sopenharmony_ci int r; 33153a5a1b3Sopenharmony_ci 33253a5a1b3Sopenharmony_ci pa_assert(conn); 33353a5a1b3Sopenharmony_ci pa_assert(msg); 33453a5a1b3Sopenharmony_ci pa_assert(iter); 33553a5a1b3Sopenharmony_ci pa_assert(c); 33653a5a1b3Sopenharmony_ci 33753a5a1b3Sopenharmony_ci dbus_message_iter_get_basic(iter, &new_active_path); 33853a5a1b3Sopenharmony_ci 33953a5a1b3Sopenharmony_ci PA_HASHMAP_FOREACH(profile, c->profiles, state) { 34053a5a1b3Sopenharmony_ci if (pa_streq(pa_dbusiface_card_profile_get_path(profile), new_active_path)) { 34153a5a1b3Sopenharmony_ci new_active = profile; 34253a5a1b3Sopenharmony_ci break; 34353a5a1b3Sopenharmony_ci } 34453a5a1b3Sopenharmony_ci } 34553a5a1b3Sopenharmony_ci 34653a5a1b3Sopenharmony_ci if (!new_active) { 34753a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such profile.", new_active_path); 34853a5a1b3Sopenharmony_ci return; 34953a5a1b3Sopenharmony_ci } 35053a5a1b3Sopenharmony_ci 35153a5a1b3Sopenharmony_ci if ((r = pa_card_set_profile(c->card, pa_dbusiface_card_profile_get_profile(new_active), true)) < 0) { 35253a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, 35353a5a1b3Sopenharmony_ci "Internal error in PulseAudio: pa_card_set_profile() failed with error code %i.", r); 35453a5a1b3Sopenharmony_ci return; 35553a5a1b3Sopenharmony_ci } 35653a5a1b3Sopenharmony_ci 35753a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 35853a5a1b3Sopenharmony_ci} 35953a5a1b3Sopenharmony_ci 36053a5a1b3Sopenharmony_cistatic void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { 36153a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 36253a5a1b3Sopenharmony_ci 36353a5a1b3Sopenharmony_ci pa_assert(conn); 36453a5a1b3Sopenharmony_ci pa_assert(msg); 36553a5a1b3Sopenharmony_ci pa_assert(c); 36653a5a1b3Sopenharmony_ci 36753a5a1b3Sopenharmony_ci pa_dbus_send_proplist_variant_reply(conn, msg, c->proplist); 36853a5a1b3Sopenharmony_ci} 36953a5a1b3Sopenharmony_ci 37053a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { 37153a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 37253a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 37353a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 37453a5a1b3Sopenharmony_ci DBusMessageIter dict_iter; 37553a5a1b3Sopenharmony_ci dbus_uint32_t idx; 37653a5a1b3Sopenharmony_ci const char *owner_module = NULL; 37753a5a1b3Sopenharmony_ci const char **sinks = NULL; 37853a5a1b3Sopenharmony_ci unsigned n_sinks = 0; 37953a5a1b3Sopenharmony_ci const char **sources = NULL; 38053a5a1b3Sopenharmony_ci unsigned n_sources = 0; 38153a5a1b3Sopenharmony_ci const char **profiles = NULL; 38253a5a1b3Sopenharmony_ci unsigned n_profiles = 0; 38353a5a1b3Sopenharmony_ci const char *active_profile = NULL; 38453a5a1b3Sopenharmony_ci 38553a5a1b3Sopenharmony_ci pa_assert(conn); 38653a5a1b3Sopenharmony_ci pa_assert(msg); 38753a5a1b3Sopenharmony_ci pa_assert(c); 38853a5a1b3Sopenharmony_ci 38953a5a1b3Sopenharmony_ci idx = c->card->index; 39053a5a1b3Sopenharmony_ci if (c->card->module) 39153a5a1b3Sopenharmony_ci owner_module = pa_dbusiface_core_get_module_path(c->core, c->card->module); 39253a5a1b3Sopenharmony_ci sinks = get_sinks(c, &n_sinks); 39353a5a1b3Sopenharmony_ci sources = get_sources(c, &n_sources); 39453a5a1b3Sopenharmony_ci profiles = get_profiles(c, &n_profiles); 39553a5a1b3Sopenharmony_ci active_profile = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name)); 39653a5a1b3Sopenharmony_ci 39753a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(msg))); 39853a5a1b3Sopenharmony_ci 39953a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 40053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); 40153a5a1b3Sopenharmony_ci 40253a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); 40353a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &c->card->name); 40453a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &c->card->driver); 40553a5a1b3Sopenharmony_ci 40653a5a1b3Sopenharmony_ci if (owner_module) 40753a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module); 40853a5a1b3Sopenharmony_ci 40953a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, sinks, n_sinks); 41053a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SOURCES].property_name, DBUS_TYPE_OBJECT_PATH, sources, n_sources); 41153a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROFILES].property_name, DBUS_TYPE_OBJECT_PATH, profiles, n_profiles); 41253a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACTIVE_PROFILE].property_name, DBUS_TYPE_OBJECT_PATH, &active_profile); 41353a5a1b3Sopenharmony_ci 41453a5a1b3Sopenharmony_ci pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, c->proplist); 41553a5a1b3Sopenharmony_ci 41653a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); 41753a5a1b3Sopenharmony_ci 41853a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(conn, reply, NULL)); 41953a5a1b3Sopenharmony_ci 42053a5a1b3Sopenharmony_ci dbus_message_unref(reply); 42153a5a1b3Sopenharmony_ci 42253a5a1b3Sopenharmony_ci pa_xfree(sinks); 42353a5a1b3Sopenharmony_ci pa_xfree(sources); 42453a5a1b3Sopenharmony_ci pa_xfree(profiles); 42553a5a1b3Sopenharmony_ci} 42653a5a1b3Sopenharmony_ci 42753a5a1b3Sopenharmony_cistatic void handle_get_profile_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { 42853a5a1b3Sopenharmony_ci pa_dbusiface_card *c = userdata; 42953a5a1b3Sopenharmony_ci const char *profile_name = NULL; 43053a5a1b3Sopenharmony_ci pa_dbusiface_card_profile *profile = NULL; 43153a5a1b3Sopenharmony_ci const char *profile_path = NULL; 43253a5a1b3Sopenharmony_ci 43353a5a1b3Sopenharmony_ci pa_assert(conn); 43453a5a1b3Sopenharmony_ci pa_assert(msg); 43553a5a1b3Sopenharmony_ci pa_assert(c); 43653a5a1b3Sopenharmony_ci 43753a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &profile_name, DBUS_TYPE_INVALID)); 43853a5a1b3Sopenharmony_ci 43953a5a1b3Sopenharmony_ci if (!(profile = pa_hashmap_get(c->profiles, profile_name))) { 44053a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such profile on card %s.", profile_name, c->card->name); 44153a5a1b3Sopenharmony_ci return; 44253a5a1b3Sopenharmony_ci } 44353a5a1b3Sopenharmony_ci 44453a5a1b3Sopenharmony_ci profile_path = pa_dbusiface_card_profile_get_path(profile); 44553a5a1b3Sopenharmony_ci 44653a5a1b3Sopenharmony_ci pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &profile_path); 44753a5a1b3Sopenharmony_ci} 44853a5a1b3Sopenharmony_ci 44953a5a1b3Sopenharmony_cistatic void check_card_proplist(pa_dbusiface_card *c) { 45053a5a1b3Sopenharmony_ci DBusMessage *signal_msg; 45153a5a1b3Sopenharmony_ci 45253a5a1b3Sopenharmony_ci if (!pa_proplist_equal(c->proplist, c->card->proplist)) { 45353a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 45453a5a1b3Sopenharmony_ci 45553a5a1b3Sopenharmony_ci pa_proplist_update(c->proplist, PA_UPDATE_SET, c->card->proplist); 45653a5a1b3Sopenharmony_ci 45753a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(c->path, 45853a5a1b3Sopenharmony_ci PA_DBUSIFACE_CARD_INTERFACE, 45953a5a1b3Sopenharmony_ci signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); 46053a5a1b3Sopenharmony_ci dbus_message_iter_init_append(signal_msg, &msg_iter); 46153a5a1b3Sopenharmony_ci pa_dbus_append_proplist(&msg_iter, c->proplist); 46253a5a1b3Sopenharmony_ci 46353a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); 46453a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 46553a5a1b3Sopenharmony_ci } 46653a5a1b3Sopenharmony_ci} 46753a5a1b3Sopenharmony_ci 46853a5a1b3Sopenharmony_cistatic pa_hook_result_t card_profile_changed_cb(void *hook_data, void *call_data, void *slot_data) { 46953a5a1b3Sopenharmony_ci pa_dbusiface_card *dbus_card = slot_data; 47053a5a1b3Sopenharmony_ci pa_card *core_card = call_data; 47153a5a1b3Sopenharmony_ci const char *object_path; 47253a5a1b3Sopenharmony_ci DBusMessage *signal_msg; 47353a5a1b3Sopenharmony_ci 47453a5a1b3Sopenharmony_ci if (dbus_card->card != core_card) 47553a5a1b3Sopenharmony_ci return PA_HOOK_OK; 47653a5a1b3Sopenharmony_ci 47753a5a1b3Sopenharmony_ci dbus_card->active_profile = dbus_card->card->active_profile; 47853a5a1b3Sopenharmony_ci 47953a5a1b3Sopenharmony_ci object_path = pa_dbusiface_card_profile_get_path(pa_hashmap_get(dbus_card->profiles, dbus_card->active_profile->name)); 48053a5a1b3Sopenharmony_ci 48153a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(dbus_card->path, 48253a5a1b3Sopenharmony_ci PA_DBUSIFACE_CARD_INTERFACE, 48353a5a1b3Sopenharmony_ci signals[SIGNAL_ACTIVE_PROFILE_UPDATED].name)); 48453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); 48553a5a1b3Sopenharmony_ci 48653a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(dbus_card->dbus_protocol, signal_msg); 48753a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 48853a5a1b3Sopenharmony_ci 48953a5a1b3Sopenharmony_ci check_card_proplist(dbus_card); 49053a5a1b3Sopenharmony_ci 49153a5a1b3Sopenharmony_ci return PA_HOOK_OK; 49253a5a1b3Sopenharmony_ci} 49353a5a1b3Sopenharmony_ci 49453a5a1b3Sopenharmony_cistatic pa_hook_result_t card_profile_added_cb(void *hook_data, void *call_data, void *slot_data) { 49553a5a1b3Sopenharmony_ci pa_core *core = hook_data; 49653a5a1b3Sopenharmony_ci pa_dbusiface_card *c = slot_data; 49753a5a1b3Sopenharmony_ci pa_card_profile *profile = call_data; 49853a5a1b3Sopenharmony_ci pa_dbusiface_card_profile *p; 49953a5a1b3Sopenharmony_ci const char *object_path; 50053a5a1b3Sopenharmony_ci DBusMessage *signal_msg; 50153a5a1b3Sopenharmony_ci 50253a5a1b3Sopenharmony_ci if (profile->card != c->card) 50353a5a1b3Sopenharmony_ci return PA_HOOK_OK; 50453a5a1b3Sopenharmony_ci 50553a5a1b3Sopenharmony_ci p = pa_dbusiface_card_profile_new(c, core, profile, c->next_profile_index++); 50653a5a1b3Sopenharmony_ci pa_assert_se(pa_hashmap_put(c->profiles, (char *) pa_dbusiface_card_profile_get_name(p), p) >= 0); 50753a5a1b3Sopenharmony_ci 50853a5a1b3Sopenharmony_ci /* Send D-Bus signal */ 50953a5a1b3Sopenharmony_ci object_path = pa_dbusiface_card_profile_get_path(p); 51053a5a1b3Sopenharmony_ci 51153a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(c->path, 51253a5a1b3Sopenharmony_ci PA_DBUSIFACE_CARD_INTERFACE, 51353a5a1b3Sopenharmony_ci signals[SIGNAL_NEW_PROFILE].name)); 51453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); 51553a5a1b3Sopenharmony_ci 51653a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); 51753a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 51853a5a1b3Sopenharmony_ci 51953a5a1b3Sopenharmony_ci check_card_proplist(c); 52053a5a1b3Sopenharmony_ci 52153a5a1b3Sopenharmony_ci return PA_HOOK_OK; 52253a5a1b3Sopenharmony_ci} 52353a5a1b3Sopenharmony_ci 52453a5a1b3Sopenharmony_cistatic pa_hook_result_t card_profile_available_changed_cb(void *hook_data, void *call_data, void *slot_data) { 52553a5a1b3Sopenharmony_ci pa_dbusiface_card *c = slot_data; 52653a5a1b3Sopenharmony_ci pa_card_profile *profile = call_data; 52753a5a1b3Sopenharmony_ci pa_dbusiface_card_profile *p; 52853a5a1b3Sopenharmony_ci const char *object_path; 52953a5a1b3Sopenharmony_ci dbus_bool_t available; 53053a5a1b3Sopenharmony_ci DBusMessage *signal_msg; 53153a5a1b3Sopenharmony_ci 53253a5a1b3Sopenharmony_ci if (profile->card != c->card) 53353a5a1b3Sopenharmony_ci return PA_HOOK_OK; 53453a5a1b3Sopenharmony_ci 53553a5a1b3Sopenharmony_ci pa_assert_se((p = pa_hashmap_get(c->profiles, profile->name))); 53653a5a1b3Sopenharmony_ci 53753a5a1b3Sopenharmony_ci object_path = pa_dbusiface_card_profile_get_path(p); 53853a5a1b3Sopenharmony_ci available = profile->available != PA_AVAILABLE_NO; 53953a5a1b3Sopenharmony_ci 54053a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(c->path, 54153a5a1b3Sopenharmony_ci PA_DBUSIFACE_CARD_INTERFACE, 54253a5a1b3Sopenharmony_ci signals[SIGNAL_PROFILE_AVAILABLE_CHANGED].name)); 54353a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, 54453a5a1b3Sopenharmony_ci DBUS_TYPE_BOOLEAN, &available, 54553a5a1b3Sopenharmony_ci DBUS_TYPE_INVALID)); 54653a5a1b3Sopenharmony_ci 54753a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); 54853a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 54953a5a1b3Sopenharmony_ci 55053a5a1b3Sopenharmony_ci check_card_proplist(c); 55153a5a1b3Sopenharmony_ci 55253a5a1b3Sopenharmony_ci return PA_HOOK_OK; 55353a5a1b3Sopenharmony_ci} 55453a5a1b3Sopenharmony_ci 55553a5a1b3Sopenharmony_cipa_dbusiface_card *pa_dbusiface_card_new(pa_dbusiface_core *core, pa_card *card) { 55653a5a1b3Sopenharmony_ci pa_dbusiface_card *c = NULL; 55753a5a1b3Sopenharmony_ci pa_card_profile *profile; 55853a5a1b3Sopenharmony_ci void *state; 55953a5a1b3Sopenharmony_ci 56053a5a1b3Sopenharmony_ci pa_assert(core); 56153a5a1b3Sopenharmony_ci pa_assert(card); 56253a5a1b3Sopenharmony_ci 56353a5a1b3Sopenharmony_ci c = pa_xnew0(pa_dbusiface_card, 1); 56453a5a1b3Sopenharmony_ci c->core = core; 56553a5a1b3Sopenharmony_ci c->card = card; 56653a5a1b3Sopenharmony_ci c->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME, card->index); 56753a5a1b3Sopenharmony_ci c->profiles = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, 56853a5a1b3Sopenharmony_ci (pa_free_cb_t) pa_dbusiface_card_profile_free); 56953a5a1b3Sopenharmony_ci c->next_profile_index = 0; 57053a5a1b3Sopenharmony_ci c->active_profile = card->active_profile; 57153a5a1b3Sopenharmony_ci c->proplist = pa_proplist_copy(card->proplist); 57253a5a1b3Sopenharmony_ci c->dbus_protocol = pa_dbus_protocol_get(card->core); 57353a5a1b3Sopenharmony_ci 57453a5a1b3Sopenharmony_ci PA_HASHMAP_FOREACH(profile, card->profiles, state) { 57553a5a1b3Sopenharmony_ci pa_dbusiface_card_profile *p = pa_dbusiface_card_profile_new(c, card->core, profile, c->next_profile_index++); 57653a5a1b3Sopenharmony_ci pa_hashmap_put(c->profiles, (char *) pa_dbusiface_card_profile_get_name(p), p); 57753a5a1b3Sopenharmony_ci } 57853a5a1b3Sopenharmony_ci 57953a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_add_interface(c->dbus_protocol, c->path, &card_interface_info, c) >= 0); 58053a5a1b3Sopenharmony_ci 58153a5a1b3Sopenharmony_ci c->card_profile_changed_slot = pa_hook_connect(&card->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], PA_HOOK_NORMAL, 58253a5a1b3Sopenharmony_ci card_profile_changed_cb, c); 58353a5a1b3Sopenharmony_ci c->card_profile_added_slot = pa_hook_connect(&card->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], PA_HOOK_NORMAL, 58453a5a1b3Sopenharmony_ci card_profile_added_cb, c); 58553a5a1b3Sopenharmony_ci c->card_profile_available_slot = pa_hook_connect(&card->core->hooks[PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED], PA_HOOK_NORMAL, 58653a5a1b3Sopenharmony_ci card_profile_available_changed_cb, c); 58753a5a1b3Sopenharmony_ci 58853a5a1b3Sopenharmony_ci return c; 58953a5a1b3Sopenharmony_ci} 59053a5a1b3Sopenharmony_ci 59153a5a1b3Sopenharmony_civoid pa_dbusiface_card_free(pa_dbusiface_card *c) { 59253a5a1b3Sopenharmony_ci pa_assert(c); 59353a5a1b3Sopenharmony_ci 59453a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_remove_interface(c->dbus_protocol, c->path, card_interface_info.name) >= 0); 59553a5a1b3Sopenharmony_ci 59653a5a1b3Sopenharmony_ci pa_hook_slot_free(c->card_profile_added_slot); 59753a5a1b3Sopenharmony_ci pa_hook_slot_free(c->card_profile_changed_slot); 59853a5a1b3Sopenharmony_ci pa_hook_slot_free(c->card_profile_available_slot); 59953a5a1b3Sopenharmony_ci 60053a5a1b3Sopenharmony_ci pa_hashmap_free(c->profiles); 60153a5a1b3Sopenharmony_ci pa_proplist_free(c->proplist); 60253a5a1b3Sopenharmony_ci pa_dbus_protocol_unref(c->dbus_protocol); 60353a5a1b3Sopenharmony_ci 60453a5a1b3Sopenharmony_ci pa_xfree(c->path); 60553a5a1b3Sopenharmony_ci pa_xfree(c); 60653a5a1b3Sopenharmony_ci} 60753a5a1b3Sopenharmony_ci 60853a5a1b3Sopenharmony_ciconst char *pa_dbusiface_card_get_path(pa_dbusiface_card *c) { 60953a5a1b3Sopenharmony_ci pa_assert(c); 61053a5a1b3Sopenharmony_ci 61153a5a1b3Sopenharmony_ci return c->path; 61253a5a1b3Sopenharmony_ci} 613