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 <pulsecore/core-util.h> 2553a5a1b3Sopenharmony_ci#include <pulsecore/dbus-util.h> 2653a5a1b3Sopenharmony_ci#include <pulsecore/protocol-dbus.h> 2753a5a1b3Sopenharmony_ci 2853a5a1b3Sopenharmony_ci#include "iface-device-port.h" 2953a5a1b3Sopenharmony_ci 3053a5a1b3Sopenharmony_ci#include "iface-device.h" 3153a5a1b3Sopenharmony_ci 3253a5a1b3Sopenharmony_ci#define SINK_OBJECT_NAME "sink" 3353a5a1b3Sopenharmony_ci#define SOURCE_OBJECT_NAME "source" 3453a5a1b3Sopenharmony_ci 3553a5a1b3Sopenharmony_cistatic void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); 3653a5a1b3Sopenharmony_cistatic void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); 3753a5a1b3Sopenharmony_cistatic void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata); 3853a5a1b3Sopenharmony_cistatic void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata); 3953a5a1b3Sopenharmony_cistatic void handle_get_card(DBusConnection *conn, DBusMessage *msg, void *userdata); 4053a5a1b3Sopenharmony_cistatic void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata); 4153a5a1b3Sopenharmony_cistatic void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata); 4253a5a1b3Sopenharmony_cistatic void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata); 4353a5a1b3Sopenharmony_cistatic void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); 4453a5a1b3Sopenharmony_cistatic void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); 4553a5a1b3Sopenharmony_cistatic void handle_get_has_flat_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); 4653a5a1b3Sopenharmony_cistatic void handle_get_has_convertible_to_decibel_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); 4753a5a1b3Sopenharmony_cistatic void handle_get_base_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); 4853a5a1b3Sopenharmony_cistatic void handle_get_volume_steps(DBusConnection *conn, DBusMessage *msg, void *userdata); 4953a5a1b3Sopenharmony_cistatic void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata); 5053a5a1b3Sopenharmony_cistatic void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); 5153a5a1b3Sopenharmony_cistatic void handle_get_has_hardware_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); 5253a5a1b3Sopenharmony_cistatic void handle_get_has_hardware_mute(DBusConnection *conn, DBusMessage *msg, void *userdata); 5353a5a1b3Sopenharmony_cistatic void handle_get_configured_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); 5453a5a1b3Sopenharmony_cistatic void handle_get_has_dynamic_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); 5553a5a1b3Sopenharmony_cistatic void handle_get_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); 5653a5a1b3Sopenharmony_cistatic void handle_get_is_hardware_device(DBusConnection *conn, DBusMessage *msg, void *userdata); 5753a5a1b3Sopenharmony_cistatic void handle_get_is_network_device(DBusConnection *conn, DBusMessage *msg, void *userdata); 5853a5a1b3Sopenharmony_cistatic void handle_get_state(DBusConnection *conn, DBusMessage *msg, void *userdata); 5953a5a1b3Sopenharmony_cistatic void handle_get_ports(DBusConnection *conn, DBusMessage *msg, void *userdata); 6053a5a1b3Sopenharmony_cistatic void handle_get_active_port(DBusConnection *conn, DBusMessage *msg, void *userdata); 6153a5a1b3Sopenharmony_cistatic void handle_set_active_port(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); 6253a5a1b3Sopenharmony_cistatic void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); 6353a5a1b3Sopenharmony_ci 6453a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); 6553a5a1b3Sopenharmony_ci 6653a5a1b3Sopenharmony_cistatic void handle_suspend(DBusConnection *conn, DBusMessage *msg, void *userdata); 6753a5a1b3Sopenharmony_cistatic void handle_get_port_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); 6853a5a1b3Sopenharmony_ci 6953a5a1b3Sopenharmony_cistatic void handle_sink_get_monitor_source(DBusConnection *conn, DBusMessage *msg, void *userdata); 7053a5a1b3Sopenharmony_ci 7153a5a1b3Sopenharmony_cistatic void handle_sink_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); 7253a5a1b3Sopenharmony_ci 7353a5a1b3Sopenharmony_cistatic void handle_source_get_monitor_of_sink(DBusConnection *conn, DBusMessage *msg, void *userdata); 7453a5a1b3Sopenharmony_ci 7553a5a1b3Sopenharmony_cistatic void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); 7653a5a1b3Sopenharmony_ci 7753a5a1b3Sopenharmony_cistruct pa_dbusiface_device { 7853a5a1b3Sopenharmony_ci pa_dbusiface_core *core; 7953a5a1b3Sopenharmony_ci 8053a5a1b3Sopenharmony_ci union { 8153a5a1b3Sopenharmony_ci pa_sink *sink; 8253a5a1b3Sopenharmony_ci pa_source *source; 8353a5a1b3Sopenharmony_ci }; 8453a5a1b3Sopenharmony_ci pa_device_type_t type; 8553a5a1b3Sopenharmony_ci char *path; 8653a5a1b3Sopenharmony_ci pa_cvolume volume; 8753a5a1b3Sopenharmony_ci dbus_bool_t mute; 8853a5a1b3Sopenharmony_ci union { 8953a5a1b3Sopenharmony_ci pa_sink_state_t sink_state; 9053a5a1b3Sopenharmony_ci pa_source_state_t source_state; 9153a5a1b3Sopenharmony_ci }; 9253a5a1b3Sopenharmony_ci pa_hashmap *ports; 9353a5a1b3Sopenharmony_ci uint32_t next_port_index; 9453a5a1b3Sopenharmony_ci pa_device_port *active_port; 9553a5a1b3Sopenharmony_ci pa_proplist *proplist; 9653a5a1b3Sopenharmony_ci 9753a5a1b3Sopenharmony_ci pa_hook_slot *volume_changed_slot; 9853a5a1b3Sopenharmony_ci pa_hook_slot *mute_changed_slot; 9953a5a1b3Sopenharmony_ci pa_hook_slot *state_changed_slot; 10053a5a1b3Sopenharmony_ci pa_hook_slot *port_changed_slot; 10153a5a1b3Sopenharmony_ci pa_hook_slot *proplist_changed_slot; 10253a5a1b3Sopenharmony_ci 10353a5a1b3Sopenharmony_ci pa_dbus_protocol *dbus_protocol; 10453a5a1b3Sopenharmony_ci}; 10553a5a1b3Sopenharmony_ci 10653a5a1b3Sopenharmony_cienum property_handler_index { 10753a5a1b3Sopenharmony_ci PROPERTY_HANDLER_INDEX, 10853a5a1b3Sopenharmony_ci PROPERTY_HANDLER_NAME, 10953a5a1b3Sopenharmony_ci PROPERTY_HANDLER_DRIVER, 11053a5a1b3Sopenharmony_ci PROPERTY_HANDLER_OWNER_MODULE, 11153a5a1b3Sopenharmony_ci PROPERTY_HANDLER_CARD, 11253a5a1b3Sopenharmony_ci PROPERTY_HANDLER_SAMPLE_FORMAT, 11353a5a1b3Sopenharmony_ci PROPERTY_HANDLER_SAMPLE_RATE, 11453a5a1b3Sopenharmony_ci PROPERTY_HANDLER_CHANNELS, 11553a5a1b3Sopenharmony_ci PROPERTY_HANDLER_VOLUME, 11653a5a1b3Sopenharmony_ci PROPERTY_HANDLER_HAS_FLAT_VOLUME, 11753a5a1b3Sopenharmony_ci PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME, 11853a5a1b3Sopenharmony_ci PROPERTY_HANDLER_BASE_VOLUME, 11953a5a1b3Sopenharmony_ci PROPERTY_HANDLER_VOLUME_STEPS, 12053a5a1b3Sopenharmony_ci PROPERTY_HANDLER_MUTE, 12153a5a1b3Sopenharmony_ci PROPERTY_HANDLER_HAS_HARDWARE_VOLUME, 12253a5a1b3Sopenharmony_ci PROPERTY_HANDLER_HAS_HARDWARE_MUTE, 12353a5a1b3Sopenharmony_ci PROPERTY_HANDLER_CONFIGURED_LATENCY, 12453a5a1b3Sopenharmony_ci PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY, 12553a5a1b3Sopenharmony_ci PROPERTY_HANDLER_LATENCY, 12653a5a1b3Sopenharmony_ci PROPERTY_HANDLER_IS_HARDWARE_DEVICE, 12753a5a1b3Sopenharmony_ci PROPERTY_HANDLER_IS_NETWORK_DEVICE, 12853a5a1b3Sopenharmony_ci PROPERTY_HANDLER_STATE, 12953a5a1b3Sopenharmony_ci PROPERTY_HANDLER_PORTS, 13053a5a1b3Sopenharmony_ci PROPERTY_HANDLER_ACTIVE_PORT, 13153a5a1b3Sopenharmony_ci PROPERTY_HANDLER_PROPERTY_LIST, 13253a5a1b3Sopenharmony_ci PROPERTY_HANDLER_MAX 13353a5a1b3Sopenharmony_ci}; 13453a5a1b3Sopenharmony_ci 13553a5a1b3Sopenharmony_cienum sink_property_handler_index { 13653a5a1b3Sopenharmony_ci SINK_PROPERTY_HANDLER_MONITOR_SOURCE, 13753a5a1b3Sopenharmony_ci SINK_PROPERTY_HANDLER_MAX 13853a5a1b3Sopenharmony_ci}; 13953a5a1b3Sopenharmony_ci 14053a5a1b3Sopenharmony_cienum source_property_handler_index { 14153a5a1b3Sopenharmony_ci SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK, 14253a5a1b3Sopenharmony_ci SOURCE_PROPERTY_HANDLER_MAX 14353a5a1b3Sopenharmony_ci}; 14453a5a1b3Sopenharmony_ci 14553a5a1b3Sopenharmony_cistatic pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { 14653a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, 14753a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, 14853a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_DRIVER] = { .property_name = "Driver", .type = "s", .get_cb = handle_get_driver, .set_cb = NULL }, 14953a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_OWNER_MODULE] = { .property_name = "OwnerModule", .type = "o", .get_cb = handle_get_owner_module, .set_cb = NULL }, 15053a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_CARD] = { .property_name = "Card", .type = "o", .get_cb = handle_get_card, .set_cb = NULL }, 15153a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_SAMPLE_FORMAT] = { .property_name = "SampleFormat", .type = "u", .get_cb = handle_get_sample_format, .set_cb = NULL }, 15253a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_SAMPLE_RATE] = { .property_name = "SampleRate", .type = "u", .get_cb = handle_get_sample_rate, .set_cb = NULL }, 15353a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_CHANNELS] = { .property_name = "Channels", .type = "au", .get_cb = handle_get_channels, .set_cb = NULL }, 15453a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "au", .get_cb = handle_get_volume, .set_cb = handle_set_volume }, 15553a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_HAS_FLAT_VOLUME] = { .property_name = "HasFlatVolume", .type = "b", .get_cb = handle_get_has_flat_volume, .set_cb = NULL }, 15653a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME] = { .property_name = "HasConvertibleToDecibelVolume", .type = "b", .get_cb = handle_get_has_convertible_to_decibel_volume, .set_cb = NULL }, 15753a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_BASE_VOLUME] = { .property_name = "BaseVolume", .type = "u", .get_cb = handle_get_base_volume, .set_cb = NULL }, 15853a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_VOLUME_STEPS] = { .property_name = "VolumeSteps", .type = "u", .get_cb = handle_get_volume_steps, .set_cb = NULL }, 15953a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_get_mute, .set_cb = handle_set_mute }, 16053a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_HAS_HARDWARE_VOLUME] = { .property_name = "HasHardwareVolume", .type = "b", .get_cb = handle_get_has_hardware_volume, .set_cb = NULL }, 16153a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_HAS_HARDWARE_MUTE] = { .property_name = "HasHardwareMute", .type = "b", .get_cb = handle_get_has_hardware_mute, .set_cb = NULL }, 16253a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_CONFIGURED_LATENCY] = { .property_name = "ConfiguredLatency", .type = "t", .get_cb = handle_get_configured_latency, .set_cb = NULL }, 16353a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY] = { .property_name = "HasDynamicLatency", .type = "b", .get_cb = handle_get_has_dynamic_latency, .set_cb = NULL }, 16453a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_LATENCY] = { .property_name = "Latency", .type = "t", .get_cb = handle_get_latency, .set_cb = NULL }, 16553a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_IS_HARDWARE_DEVICE] = { .property_name = "IsHardwareDevice", .type = "b", .get_cb = handle_get_is_hardware_device, .set_cb = NULL }, 16653a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_IS_NETWORK_DEVICE] = { .property_name = "IsNetworkDevice", .type = "b", .get_cb = handle_get_is_network_device, .set_cb = NULL }, 16753a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_STATE] = { .property_name = "State", .type = "u", .get_cb = handle_get_state, .set_cb = NULL }, 16853a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_PORTS] = { .property_name = "Ports", .type = "ao", .get_cb = handle_get_ports, .set_cb = NULL }, 16953a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_ACTIVE_PORT] = { .property_name = "ActivePort", .type = "o", .get_cb = handle_get_active_port, .set_cb = handle_set_active_port }, 17053a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } 17153a5a1b3Sopenharmony_ci}; 17253a5a1b3Sopenharmony_ci 17353a5a1b3Sopenharmony_cistatic pa_dbus_property_handler sink_property_handlers[SINK_PROPERTY_HANDLER_MAX] = { 17453a5a1b3Sopenharmony_ci [SINK_PROPERTY_HANDLER_MONITOR_SOURCE] = { .property_name = "MonitorSource", .type = "o", .get_cb = handle_sink_get_monitor_source, .set_cb = NULL } 17553a5a1b3Sopenharmony_ci}; 17653a5a1b3Sopenharmony_ci 17753a5a1b3Sopenharmony_cistatic pa_dbus_property_handler source_property_handlers[SOURCE_PROPERTY_HANDLER_MAX] = { 17853a5a1b3Sopenharmony_ci [SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK] = { .property_name = "MonitorOfSink", .type = "o", .get_cb = handle_source_get_monitor_of_sink, .set_cb = NULL } 17953a5a1b3Sopenharmony_ci}; 18053a5a1b3Sopenharmony_ci 18153a5a1b3Sopenharmony_cienum method_handler_index { 18253a5a1b3Sopenharmony_ci METHOD_HANDLER_SUSPEND, 18353a5a1b3Sopenharmony_ci METHOD_HANDLER_GET_PORT_BY_NAME, 18453a5a1b3Sopenharmony_ci METHOD_HANDLER_MAX 18553a5a1b3Sopenharmony_ci}; 18653a5a1b3Sopenharmony_ci 18753a5a1b3Sopenharmony_cistatic pa_dbus_arg_info suspend_args[] = { { "suspend", "b", "in" } }; 18853a5a1b3Sopenharmony_cistatic pa_dbus_arg_info get_port_by_name_args[] = { { "name", "s", "in" }, { "port", "o", "out" } }; 18953a5a1b3Sopenharmony_ci 19053a5a1b3Sopenharmony_cistatic pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { 19153a5a1b3Sopenharmony_ci [METHOD_HANDLER_SUSPEND] = { 19253a5a1b3Sopenharmony_ci .method_name = "Suspend", 19353a5a1b3Sopenharmony_ci .arguments = suspend_args, 19453a5a1b3Sopenharmony_ci .n_arguments = sizeof(suspend_args) / sizeof(pa_dbus_arg_info), 19553a5a1b3Sopenharmony_ci .receive_cb = handle_suspend }, 19653a5a1b3Sopenharmony_ci [METHOD_HANDLER_GET_PORT_BY_NAME] = { 19753a5a1b3Sopenharmony_ci .method_name = "GetPortByName", 19853a5a1b3Sopenharmony_ci .arguments = get_port_by_name_args, 19953a5a1b3Sopenharmony_ci .n_arguments = sizeof(get_port_by_name_args) / sizeof(pa_dbus_arg_info), 20053a5a1b3Sopenharmony_ci .receive_cb = handle_get_port_by_name } 20153a5a1b3Sopenharmony_ci}; 20253a5a1b3Sopenharmony_ci 20353a5a1b3Sopenharmony_cienum signal_index { 20453a5a1b3Sopenharmony_ci SIGNAL_VOLUME_UPDATED, 20553a5a1b3Sopenharmony_ci SIGNAL_MUTE_UPDATED, 20653a5a1b3Sopenharmony_ci SIGNAL_STATE_UPDATED, 20753a5a1b3Sopenharmony_ci SIGNAL_ACTIVE_PORT_UPDATED, 20853a5a1b3Sopenharmony_ci SIGNAL_PROPERTY_LIST_UPDATED, 20953a5a1b3Sopenharmony_ci SIGNAL_MAX 21053a5a1b3Sopenharmony_ci}; 21153a5a1b3Sopenharmony_ci 21253a5a1b3Sopenharmony_cistatic pa_dbus_arg_info volume_updated_args[] = { { "volume", "au", NULL } }; 21353a5a1b3Sopenharmony_cistatic pa_dbus_arg_info mute_updated_args[] = { { "muted", "b", NULL } }; 21453a5a1b3Sopenharmony_cistatic pa_dbus_arg_info state_updated_args[] = { { "state", "u", NULL } }; 21553a5a1b3Sopenharmony_cistatic pa_dbus_arg_info active_port_updated_args[] = { { "port", "o", NULL } }; 21653a5a1b3Sopenharmony_cistatic pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; 21753a5a1b3Sopenharmony_ci 21853a5a1b3Sopenharmony_cistatic pa_dbus_signal_info signals[SIGNAL_MAX] = { 21953a5a1b3Sopenharmony_ci [SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = volume_updated_args, .n_arguments = 1 }, 22053a5a1b3Sopenharmony_ci [SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = mute_updated_args, .n_arguments = 1 }, 22153a5a1b3Sopenharmony_ci [SIGNAL_STATE_UPDATED] = { .name = "StateUpdated", .arguments = state_updated_args, .n_arguments = 1 }, 22253a5a1b3Sopenharmony_ci [SIGNAL_ACTIVE_PORT_UPDATED] = { .name = "ActivePortUpdated", .arguments = active_port_updated_args, .n_arguments = 1 }, 22353a5a1b3Sopenharmony_ci [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 } 22453a5a1b3Sopenharmony_ci}; 22553a5a1b3Sopenharmony_ci 22653a5a1b3Sopenharmony_cistatic pa_dbus_interface_info device_interface_info = { 22753a5a1b3Sopenharmony_ci .name = PA_DBUSIFACE_DEVICE_INTERFACE, 22853a5a1b3Sopenharmony_ci .method_handlers = method_handlers, 22953a5a1b3Sopenharmony_ci .n_method_handlers = METHOD_HANDLER_MAX, 23053a5a1b3Sopenharmony_ci .property_handlers = property_handlers, 23153a5a1b3Sopenharmony_ci .n_property_handlers = PROPERTY_HANDLER_MAX, 23253a5a1b3Sopenharmony_ci .get_all_properties_cb = handle_get_all, 23353a5a1b3Sopenharmony_ci .signals = signals, 23453a5a1b3Sopenharmony_ci .n_signals = SIGNAL_MAX 23553a5a1b3Sopenharmony_ci}; 23653a5a1b3Sopenharmony_ci 23753a5a1b3Sopenharmony_cistatic pa_dbus_interface_info sink_interface_info = { 23853a5a1b3Sopenharmony_ci .name = PA_DBUSIFACE_SINK_INTERFACE, 23953a5a1b3Sopenharmony_ci .method_handlers = NULL, 24053a5a1b3Sopenharmony_ci .n_method_handlers = 0, 24153a5a1b3Sopenharmony_ci .property_handlers = sink_property_handlers, 24253a5a1b3Sopenharmony_ci .n_property_handlers = SINK_PROPERTY_HANDLER_MAX, 24353a5a1b3Sopenharmony_ci .get_all_properties_cb = handle_sink_get_all, 24453a5a1b3Sopenharmony_ci .signals = NULL, 24553a5a1b3Sopenharmony_ci .n_signals = 0 24653a5a1b3Sopenharmony_ci}; 24753a5a1b3Sopenharmony_ci 24853a5a1b3Sopenharmony_cistatic pa_dbus_interface_info source_interface_info = { 24953a5a1b3Sopenharmony_ci .name = PA_DBUSIFACE_SOURCE_INTERFACE, 25053a5a1b3Sopenharmony_ci .method_handlers = NULL, 25153a5a1b3Sopenharmony_ci .n_method_handlers = 0, 25253a5a1b3Sopenharmony_ci .property_handlers = source_property_handlers, 25353a5a1b3Sopenharmony_ci .n_property_handlers = SOURCE_PROPERTY_HANDLER_MAX, 25453a5a1b3Sopenharmony_ci .get_all_properties_cb = handle_source_get_all, 25553a5a1b3Sopenharmony_ci .signals = NULL, 25653a5a1b3Sopenharmony_ci .n_signals = 0 25753a5a1b3Sopenharmony_ci}; 25853a5a1b3Sopenharmony_ci 25953a5a1b3Sopenharmony_cistatic void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { 26053a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 26153a5a1b3Sopenharmony_ci dbus_uint32_t idx = 0; 26253a5a1b3Sopenharmony_ci 26353a5a1b3Sopenharmony_ci pa_assert(conn); 26453a5a1b3Sopenharmony_ci pa_assert(msg); 26553a5a1b3Sopenharmony_ci pa_assert(d); 26653a5a1b3Sopenharmony_ci 26753a5a1b3Sopenharmony_ci idx = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->index : d->source->index; 26853a5a1b3Sopenharmony_ci 26953a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); 27053a5a1b3Sopenharmony_ci} 27153a5a1b3Sopenharmony_ci 27253a5a1b3Sopenharmony_cistatic void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { 27353a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 27453a5a1b3Sopenharmony_ci const char *name = NULL; 27553a5a1b3Sopenharmony_ci 27653a5a1b3Sopenharmony_ci pa_assert(conn); 27753a5a1b3Sopenharmony_ci pa_assert(msg); 27853a5a1b3Sopenharmony_ci pa_assert(d); 27953a5a1b3Sopenharmony_ci 28053a5a1b3Sopenharmony_ci name = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->name : d->source->name; 28153a5a1b3Sopenharmony_ci 28253a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &name); 28353a5a1b3Sopenharmony_ci} 28453a5a1b3Sopenharmony_ci 28553a5a1b3Sopenharmony_cistatic void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) { 28653a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 28753a5a1b3Sopenharmony_ci const char *driver = NULL; 28853a5a1b3Sopenharmony_ci 28953a5a1b3Sopenharmony_ci pa_assert(conn); 29053a5a1b3Sopenharmony_ci pa_assert(msg); 29153a5a1b3Sopenharmony_ci pa_assert(d); 29253a5a1b3Sopenharmony_ci 29353a5a1b3Sopenharmony_ci driver = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->driver : d->source->driver; 29453a5a1b3Sopenharmony_ci 29553a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &driver); 29653a5a1b3Sopenharmony_ci} 29753a5a1b3Sopenharmony_ci 29853a5a1b3Sopenharmony_cistatic void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) { 29953a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 30053a5a1b3Sopenharmony_ci pa_module *owner_module = NULL; 30153a5a1b3Sopenharmony_ci const char *object_path = NULL; 30253a5a1b3Sopenharmony_ci 30353a5a1b3Sopenharmony_ci pa_assert(conn); 30453a5a1b3Sopenharmony_ci pa_assert(msg); 30553a5a1b3Sopenharmony_ci pa_assert(d); 30653a5a1b3Sopenharmony_ci 30753a5a1b3Sopenharmony_ci owner_module = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->module : d->source->module; 30853a5a1b3Sopenharmony_ci 30953a5a1b3Sopenharmony_ci if (!owner_module) { 31053a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 31153a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 31253a5a1b3Sopenharmony_ci "Sink %s doesn't have an owner module.", d->sink->name); 31353a5a1b3Sopenharmony_ci else 31453a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 31553a5a1b3Sopenharmony_ci "Source %s doesn't have an owner module.", d->source->name); 31653a5a1b3Sopenharmony_ci return; 31753a5a1b3Sopenharmony_ci } 31853a5a1b3Sopenharmony_ci 31953a5a1b3Sopenharmony_ci object_path = pa_dbusiface_core_get_module_path(d->core, owner_module); 32053a5a1b3Sopenharmony_ci 32153a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); 32253a5a1b3Sopenharmony_ci} 32353a5a1b3Sopenharmony_ci 32453a5a1b3Sopenharmony_cistatic void handle_get_card(DBusConnection *conn, DBusMessage *msg, void *userdata) { 32553a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 32653a5a1b3Sopenharmony_ci pa_card *card = NULL; 32753a5a1b3Sopenharmony_ci const char *object_path = NULL; 32853a5a1b3Sopenharmony_ci 32953a5a1b3Sopenharmony_ci pa_assert(conn); 33053a5a1b3Sopenharmony_ci pa_assert(msg); 33153a5a1b3Sopenharmony_ci pa_assert(d); 33253a5a1b3Sopenharmony_ci 33353a5a1b3Sopenharmony_ci card = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->card : d->source->card; 33453a5a1b3Sopenharmony_ci 33553a5a1b3Sopenharmony_ci if (!card) { 33653a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 33753a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 33853a5a1b3Sopenharmony_ci "Sink %s doesn't belong to any card.", d->sink->name); 33953a5a1b3Sopenharmony_ci else 34053a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 34153a5a1b3Sopenharmony_ci "Source %s doesn't belong to any card.", d->source->name); 34253a5a1b3Sopenharmony_ci return; 34353a5a1b3Sopenharmony_ci } 34453a5a1b3Sopenharmony_ci 34553a5a1b3Sopenharmony_ci object_path = pa_dbusiface_core_get_card_path(d->core, card); 34653a5a1b3Sopenharmony_ci 34753a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); 34853a5a1b3Sopenharmony_ci} 34953a5a1b3Sopenharmony_ci 35053a5a1b3Sopenharmony_cistatic void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) { 35153a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 35253a5a1b3Sopenharmony_ci dbus_uint32_t sample_format = 0; 35353a5a1b3Sopenharmony_ci 35453a5a1b3Sopenharmony_ci pa_assert(conn); 35553a5a1b3Sopenharmony_ci pa_assert(msg); 35653a5a1b3Sopenharmony_ci pa_assert(d); 35753a5a1b3Sopenharmony_ci 35853a5a1b3Sopenharmony_ci sample_format = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->sample_spec.format : d->source->sample_spec.format; 35953a5a1b3Sopenharmony_ci 36053a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format); 36153a5a1b3Sopenharmony_ci} 36253a5a1b3Sopenharmony_ci 36353a5a1b3Sopenharmony_cistatic void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) { 36453a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 36553a5a1b3Sopenharmony_ci dbus_uint32_t sample_rate = 0; 36653a5a1b3Sopenharmony_ci 36753a5a1b3Sopenharmony_ci pa_assert(conn); 36853a5a1b3Sopenharmony_ci pa_assert(msg); 36953a5a1b3Sopenharmony_ci pa_assert(d); 37053a5a1b3Sopenharmony_ci 37153a5a1b3Sopenharmony_ci sample_rate = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->sample_spec.rate : d->source->sample_spec.rate; 37253a5a1b3Sopenharmony_ci 37353a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_rate); 37453a5a1b3Sopenharmony_ci} 37553a5a1b3Sopenharmony_ci 37653a5a1b3Sopenharmony_cistatic void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) { 37753a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 37853a5a1b3Sopenharmony_ci pa_channel_map *channel_map = NULL; 37953a5a1b3Sopenharmony_ci dbus_uint32_t channels[PA_CHANNELS_MAX]; 38053a5a1b3Sopenharmony_ci unsigned i = 0; 38153a5a1b3Sopenharmony_ci 38253a5a1b3Sopenharmony_ci pa_assert(conn); 38353a5a1b3Sopenharmony_ci pa_assert(msg); 38453a5a1b3Sopenharmony_ci pa_assert(d); 38553a5a1b3Sopenharmony_ci 38653a5a1b3Sopenharmony_ci channel_map = (d->type == PA_DEVICE_TYPE_SINK) ? &d->sink->channel_map : &d->source->channel_map; 38753a5a1b3Sopenharmony_ci 38853a5a1b3Sopenharmony_ci for (i = 0; i < channel_map->channels; ++i) 38953a5a1b3Sopenharmony_ci channels[i] = channel_map->map[i]; 39053a5a1b3Sopenharmony_ci 39153a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, channels, channel_map->channels); 39253a5a1b3Sopenharmony_ci} 39353a5a1b3Sopenharmony_ci 39453a5a1b3Sopenharmony_cistatic void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { 39553a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 39653a5a1b3Sopenharmony_ci dbus_uint32_t volume[PA_CHANNELS_MAX]; 39753a5a1b3Sopenharmony_ci unsigned i = 0; 39853a5a1b3Sopenharmony_ci 39953a5a1b3Sopenharmony_ci pa_assert(conn); 40053a5a1b3Sopenharmony_ci pa_assert(msg); 40153a5a1b3Sopenharmony_ci pa_assert(d); 40253a5a1b3Sopenharmony_ci 40353a5a1b3Sopenharmony_ci for (i = 0; i < d->volume.channels; ++i) 40453a5a1b3Sopenharmony_ci volume[i] = d->volume.values[i]; 40553a5a1b3Sopenharmony_ci 40653a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, volume, d->volume.channels); 40753a5a1b3Sopenharmony_ci} 40853a5a1b3Sopenharmony_ci 40953a5a1b3Sopenharmony_cistatic void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { 41053a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 41153a5a1b3Sopenharmony_ci DBusMessageIter array_iter; 41253a5a1b3Sopenharmony_ci int device_channels = 0; 41353a5a1b3Sopenharmony_ci dbus_uint32_t *volume = NULL; 41453a5a1b3Sopenharmony_ci int n_volume_entries = 0; 41553a5a1b3Sopenharmony_ci pa_cvolume new_vol; 41653a5a1b3Sopenharmony_ci int i = 0; 41753a5a1b3Sopenharmony_ci 41853a5a1b3Sopenharmony_ci pa_assert(conn); 41953a5a1b3Sopenharmony_ci pa_assert(msg); 42053a5a1b3Sopenharmony_ci pa_assert(iter); 42153a5a1b3Sopenharmony_ci pa_assert(d); 42253a5a1b3Sopenharmony_ci 42353a5a1b3Sopenharmony_ci device_channels = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->channel_map.channels : d->source->channel_map.channels; 42453a5a1b3Sopenharmony_ci 42553a5a1b3Sopenharmony_ci dbus_message_iter_recurse(iter, &array_iter); 42653a5a1b3Sopenharmony_ci dbus_message_iter_get_fixed_array(&array_iter, &volume, &n_volume_entries); 42753a5a1b3Sopenharmony_ci 42853a5a1b3Sopenharmony_ci if (n_volume_entries != device_channels && n_volume_entries != 1) { 42953a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, 43053a5a1b3Sopenharmony_ci "Expected %u volume entries, got %i.", device_channels, n_volume_entries); 43153a5a1b3Sopenharmony_ci return; 43253a5a1b3Sopenharmony_ci } 43353a5a1b3Sopenharmony_ci 43453a5a1b3Sopenharmony_ci pa_cvolume_init(&new_vol); 43553a5a1b3Sopenharmony_ci new_vol.channels = n_volume_entries; 43653a5a1b3Sopenharmony_ci 43753a5a1b3Sopenharmony_ci for (i = 0; i < n_volume_entries; ++i) { 43853a5a1b3Sopenharmony_ci if (!PA_VOLUME_IS_VALID(volume[i])) { 43953a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too large volume value: %u", volume[i]); 44053a5a1b3Sopenharmony_ci return; 44153a5a1b3Sopenharmony_ci } 44253a5a1b3Sopenharmony_ci new_vol.values[i] = volume[i]; 44353a5a1b3Sopenharmony_ci } 44453a5a1b3Sopenharmony_ci 44553a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 44653a5a1b3Sopenharmony_ci pa_sink_set_volume(d->sink, &new_vol, true, true); 44753a5a1b3Sopenharmony_ci else 44853a5a1b3Sopenharmony_ci pa_source_set_volume(d->source, &new_vol, true, true); 44953a5a1b3Sopenharmony_ci 45053a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 45153a5a1b3Sopenharmony_ci} 45253a5a1b3Sopenharmony_ci 45353a5a1b3Sopenharmony_cistatic void handle_get_has_flat_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { 45453a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 45553a5a1b3Sopenharmony_ci dbus_bool_t has_flat_volume = FALSE; 45653a5a1b3Sopenharmony_ci 45753a5a1b3Sopenharmony_ci pa_assert(conn); 45853a5a1b3Sopenharmony_ci pa_assert(msg); 45953a5a1b3Sopenharmony_ci pa_assert(d); 46053a5a1b3Sopenharmony_ci 46153a5a1b3Sopenharmony_ci has_flat_volume = (d->type == PA_DEVICE_TYPE_SINK) ? !!(d->sink->flags & PA_SINK_FLAT_VOLUME) : FALSE; 46253a5a1b3Sopenharmony_ci 46353a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_flat_volume); 46453a5a1b3Sopenharmony_ci} 46553a5a1b3Sopenharmony_ci 46653a5a1b3Sopenharmony_cistatic void handle_get_has_convertible_to_decibel_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { 46753a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 46853a5a1b3Sopenharmony_ci dbus_bool_t has_convertible_to_decibel_volume = FALSE; 46953a5a1b3Sopenharmony_ci 47053a5a1b3Sopenharmony_ci pa_assert(conn); 47153a5a1b3Sopenharmony_ci pa_assert(msg); 47253a5a1b3Sopenharmony_ci pa_assert(d); 47353a5a1b3Sopenharmony_ci 47453a5a1b3Sopenharmony_ci has_convertible_to_decibel_volume = (d->type == PA_DEVICE_TYPE_SINK) 47553a5a1b3Sopenharmony_ci ? !!(d->sink->flags & PA_SINK_DECIBEL_VOLUME) 47653a5a1b3Sopenharmony_ci : !!(d->source->flags & PA_SOURCE_DECIBEL_VOLUME); 47753a5a1b3Sopenharmony_ci 47853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_convertible_to_decibel_volume); 47953a5a1b3Sopenharmony_ci} 48053a5a1b3Sopenharmony_ci 48153a5a1b3Sopenharmony_cistatic void handle_get_base_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { 48253a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 48353a5a1b3Sopenharmony_ci dbus_uint32_t base_volume; 48453a5a1b3Sopenharmony_ci 48553a5a1b3Sopenharmony_ci pa_assert(conn); 48653a5a1b3Sopenharmony_ci pa_assert(msg); 48753a5a1b3Sopenharmony_ci pa_assert(d); 48853a5a1b3Sopenharmony_ci 48953a5a1b3Sopenharmony_ci base_volume = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->base_volume : d->source->base_volume; 49053a5a1b3Sopenharmony_ci 49153a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &base_volume); 49253a5a1b3Sopenharmony_ci} 49353a5a1b3Sopenharmony_ci 49453a5a1b3Sopenharmony_cistatic void handle_get_volume_steps(DBusConnection *conn, DBusMessage *msg, void *userdata) { 49553a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 49653a5a1b3Sopenharmony_ci dbus_uint32_t volume_steps; 49753a5a1b3Sopenharmony_ci 49853a5a1b3Sopenharmony_ci pa_assert(conn); 49953a5a1b3Sopenharmony_ci pa_assert(msg); 50053a5a1b3Sopenharmony_ci pa_assert(d); 50153a5a1b3Sopenharmony_ci 50253a5a1b3Sopenharmony_ci volume_steps = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->n_volume_steps : d->source->n_volume_steps; 50353a5a1b3Sopenharmony_ci 50453a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &volume_steps); 50553a5a1b3Sopenharmony_ci} 50653a5a1b3Sopenharmony_ci 50753a5a1b3Sopenharmony_cistatic void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) { 50853a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 50953a5a1b3Sopenharmony_ci 51053a5a1b3Sopenharmony_ci pa_assert(conn); 51153a5a1b3Sopenharmony_ci pa_assert(msg); 51253a5a1b3Sopenharmony_ci pa_assert(d); 51353a5a1b3Sopenharmony_ci 51453a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &d->mute); 51553a5a1b3Sopenharmony_ci} 51653a5a1b3Sopenharmony_ci 51753a5a1b3Sopenharmony_cistatic void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { 51853a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 51953a5a1b3Sopenharmony_ci dbus_bool_t mute = FALSE; 52053a5a1b3Sopenharmony_ci 52153a5a1b3Sopenharmony_ci pa_assert(conn); 52253a5a1b3Sopenharmony_ci pa_assert(msg); 52353a5a1b3Sopenharmony_ci pa_assert(iter); 52453a5a1b3Sopenharmony_ci pa_assert(d); 52553a5a1b3Sopenharmony_ci 52653a5a1b3Sopenharmony_ci dbus_message_iter_get_basic(iter, &mute); 52753a5a1b3Sopenharmony_ci 52853a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 52953a5a1b3Sopenharmony_ci pa_sink_set_mute(d->sink, mute, true); 53053a5a1b3Sopenharmony_ci else 53153a5a1b3Sopenharmony_ci pa_source_set_mute(d->source, mute, true); 53253a5a1b3Sopenharmony_ci 53353a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 53453a5a1b3Sopenharmony_ci} 53553a5a1b3Sopenharmony_ci 53653a5a1b3Sopenharmony_cistatic void handle_get_has_hardware_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { 53753a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 53853a5a1b3Sopenharmony_ci dbus_bool_t has_hardware_volume = FALSE; 53953a5a1b3Sopenharmony_ci 54053a5a1b3Sopenharmony_ci pa_assert(conn); 54153a5a1b3Sopenharmony_ci pa_assert(msg); 54253a5a1b3Sopenharmony_ci pa_assert(d); 54353a5a1b3Sopenharmony_ci 54453a5a1b3Sopenharmony_ci has_hardware_volume = (d->type == PA_DEVICE_TYPE_SINK) 54553a5a1b3Sopenharmony_ci ? !!(d->sink->flags & PA_SINK_HW_VOLUME_CTRL) 54653a5a1b3Sopenharmony_ci : !!(d->source->flags & PA_SOURCE_HW_VOLUME_CTRL); 54753a5a1b3Sopenharmony_ci 54853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_hardware_volume); 54953a5a1b3Sopenharmony_ci} 55053a5a1b3Sopenharmony_ci 55153a5a1b3Sopenharmony_cistatic void handle_get_has_hardware_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) { 55253a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 55353a5a1b3Sopenharmony_ci dbus_bool_t has_hardware_mute = FALSE; 55453a5a1b3Sopenharmony_ci 55553a5a1b3Sopenharmony_ci pa_assert(conn); 55653a5a1b3Sopenharmony_ci pa_assert(msg); 55753a5a1b3Sopenharmony_ci pa_assert(d); 55853a5a1b3Sopenharmony_ci 55953a5a1b3Sopenharmony_ci has_hardware_mute = (d->type == PA_DEVICE_TYPE_SINK) 56053a5a1b3Sopenharmony_ci ? !!(d->sink->flags & PA_SINK_HW_MUTE_CTRL) 56153a5a1b3Sopenharmony_ci : !!(d->source->flags & PA_SOURCE_HW_MUTE_CTRL); 56253a5a1b3Sopenharmony_ci 56353a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_hardware_mute); 56453a5a1b3Sopenharmony_ci} 56553a5a1b3Sopenharmony_ci 56653a5a1b3Sopenharmony_cistatic void handle_get_configured_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { 56753a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 56853a5a1b3Sopenharmony_ci dbus_uint64_t configured_latency = 0; 56953a5a1b3Sopenharmony_ci 57053a5a1b3Sopenharmony_ci pa_assert(conn); 57153a5a1b3Sopenharmony_ci pa_assert(msg); 57253a5a1b3Sopenharmony_ci pa_assert(d); 57353a5a1b3Sopenharmony_ci 57453a5a1b3Sopenharmony_ci configured_latency = (d->type == PA_DEVICE_TYPE_SINK) 57553a5a1b3Sopenharmony_ci ? pa_sink_get_requested_latency(d->sink) 57653a5a1b3Sopenharmony_ci : pa_source_get_requested_latency(d->source); 57753a5a1b3Sopenharmony_ci 57853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &configured_latency); 57953a5a1b3Sopenharmony_ci} 58053a5a1b3Sopenharmony_ci 58153a5a1b3Sopenharmony_cistatic void handle_get_has_dynamic_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { 58253a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 58353a5a1b3Sopenharmony_ci dbus_bool_t has_dynamic_latency = FALSE; 58453a5a1b3Sopenharmony_ci 58553a5a1b3Sopenharmony_ci pa_assert(conn); 58653a5a1b3Sopenharmony_ci pa_assert(msg); 58753a5a1b3Sopenharmony_ci pa_assert(d); 58853a5a1b3Sopenharmony_ci 58953a5a1b3Sopenharmony_ci has_dynamic_latency = (d->type == PA_DEVICE_TYPE_SINK) 59053a5a1b3Sopenharmony_ci ? !!(d->sink->flags & PA_SINK_DYNAMIC_LATENCY) 59153a5a1b3Sopenharmony_ci : !!(d->source->flags & PA_SOURCE_DYNAMIC_LATENCY); 59253a5a1b3Sopenharmony_ci 59353a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_dynamic_latency); 59453a5a1b3Sopenharmony_ci} 59553a5a1b3Sopenharmony_ci 59653a5a1b3Sopenharmony_cistatic void handle_get_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { 59753a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 59853a5a1b3Sopenharmony_ci dbus_uint64_t latency = 0; 59953a5a1b3Sopenharmony_ci 60053a5a1b3Sopenharmony_ci pa_assert(conn); 60153a5a1b3Sopenharmony_ci pa_assert(msg); 60253a5a1b3Sopenharmony_ci pa_assert(d); 60353a5a1b3Sopenharmony_ci 60453a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK && !(d->sink->flags & PA_SINK_LATENCY)) { 60553a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 60653a5a1b3Sopenharmony_ci "Sink %s doesn't support latency querying.", d->sink->name); 60753a5a1b3Sopenharmony_ci return; 60853a5a1b3Sopenharmony_ci } 60953a5a1b3Sopenharmony_ci 61053a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SOURCE && !(d->source->flags & PA_SOURCE_LATENCY)) { 61153a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 61253a5a1b3Sopenharmony_ci "Source %s doesn't support latency querying.", d->source->name); 61353a5a1b3Sopenharmony_ci return; 61453a5a1b3Sopenharmony_ci } 61553a5a1b3Sopenharmony_ci 61653a5a1b3Sopenharmony_ci latency = (d->type == PA_DEVICE_TYPE_SINK) ? pa_sink_get_latency(d->sink) : pa_source_get_latency(d->source); 61753a5a1b3Sopenharmony_ci 61853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &latency); 61953a5a1b3Sopenharmony_ci} 62053a5a1b3Sopenharmony_ci 62153a5a1b3Sopenharmony_cistatic void handle_get_is_hardware_device(DBusConnection *conn, DBusMessage *msg, void *userdata) { 62253a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 62353a5a1b3Sopenharmony_ci dbus_bool_t is_hardware_device = FALSE; 62453a5a1b3Sopenharmony_ci 62553a5a1b3Sopenharmony_ci pa_assert(conn); 62653a5a1b3Sopenharmony_ci pa_assert(msg); 62753a5a1b3Sopenharmony_ci pa_assert(d); 62853a5a1b3Sopenharmony_ci 62953a5a1b3Sopenharmony_ci is_hardware_device = (d->type == PA_DEVICE_TYPE_SINK) 63053a5a1b3Sopenharmony_ci ? !!(d->sink->flags & PA_SINK_HARDWARE) 63153a5a1b3Sopenharmony_ci : !!(d->source->flags & PA_SOURCE_HARDWARE); 63253a5a1b3Sopenharmony_ci 63353a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_hardware_device); 63453a5a1b3Sopenharmony_ci} 63553a5a1b3Sopenharmony_ci 63653a5a1b3Sopenharmony_cistatic void handle_get_is_network_device(DBusConnection *conn, DBusMessage *msg, void *userdata) { 63753a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 63853a5a1b3Sopenharmony_ci dbus_bool_t is_network_device = FALSE; 63953a5a1b3Sopenharmony_ci 64053a5a1b3Sopenharmony_ci pa_assert(conn); 64153a5a1b3Sopenharmony_ci pa_assert(msg); 64253a5a1b3Sopenharmony_ci pa_assert(d); 64353a5a1b3Sopenharmony_ci 64453a5a1b3Sopenharmony_ci is_network_device = (d->type == PA_DEVICE_TYPE_SINK) 64553a5a1b3Sopenharmony_ci ? !!(d->sink->flags & PA_SINK_NETWORK) 64653a5a1b3Sopenharmony_ci : !!(d->source->flags & PA_SOURCE_NETWORK); 64753a5a1b3Sopenharmony_ci 64853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_network_device); 64953a5a1b3Sopenharmony_ci} 65053a5a1b3Sopenharmony_ci 65153a5a1b3Sopenharmony_cistatic void handle_get_state(DBusConnection *conn, DBusMessage *msg, void *userdata) { 65253a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 65353a5a1b3Sopenharmony_ci dbus_uint32_t state; 65453a5a1b3Sopenharmony_ci 65553a5a1b3Sopenharmony_ci pa_assert(conn); 65653a5a1b3Sopenharmony_ci pa_assert(msg); 65753a5a1b3Sopenharmony_ci pa_assert(d); 65853a5a1b3Sopenharmony_ci 65953a5a1b3Sopenharmony_ci state = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink_state : d->source_state; 66053a5a1b3Sopenharmony_ci 66153a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &state); 66253a5a1b3Sopenharmony_ci} 66353a5a1b3Sopenharmony_ci 66453a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */ 66553a5a1b3Sopenharmony_cistatic const char **get_ports(pa_dbusiface_device *d, unsigned *n) { 66653a5a1b3Sopenharmony_ci const char **ports; 66753a5a1b3Sopenharmony_ci unsigned i = 0; 66853a5a1b3Sopenharmony_ci void *state = NULL; 66953a5a1b3Sopenharmony_ci pa_dbusiface_device_port *port = NULL; 67053a5a1b3Sopenharmony_ci 67153a5a1b3Sopenharmony_ci pa_assert(d); 67253a5a1b3Sopenharmony_ci pa_assert(n); 67353a5a1b3Sopenharmony_ci 67453a5a1b3Sopenharmony_ci *n = pa_hashmap_size(d->ports); 67553a5a1b3Sopenharmony_ci 67653a5a1b3Sopenharmony_ci if (*n == 0) 67753a5a1b3Sopenharmony_ci return NULL; 67853a5a1b3Sopenharmony_ci 67953a5a1b3Sopenharmony_ci ports = pa_xnew(const char *, *n); 68053a5a1b3Sopenharmony_ci 68153a5a1b3Sopenharmony_ci PA_HASHMAP_FOREACH(port, d->ports, state) 68253a5a1b3Sopenharmony_ci ports[i++] = pa_dbusiface_device_port_get_path(port); 68353a5a1b3Sopenharmony_ci 68453a5a1b3Sopenharmony_ci return ports; 68553a5a1b3Sopenharmony_ci} 68653a5a1b3Sopenharmony_ci 68753a5a1b3Sopenharmony_cistatic void handle_get_ports(DBusConnection *conn, DBusMessage *msg, void *userdata) { 68853a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 68953a5a1b3Sopenharmony_ci const char **ports = NULL; 69053a5a1b3Sopenharmony_ci unsigned n_ports = 0; 69153a5a1b3Sopenharmony_ci 69253a5a1b3Sopenharmony_ci pa_assert(conn); 69353a5a1b3Sopenharmony_ci pa_assert(msg); 69453a5a1b3Sopenharmony_ci pa_assert(d); 69553a5a1b3Sopenharmony_ci 69653a5a1b3Sopenharmony_ci ports = get_ports(d, &n_ports); 69753a5a1b3Sopenharmony_ci 69853a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, ports, n_ports); 69953a5a1b3Sopenharmony_ci 70053a5a1b3Sopenharmony_ci pa_xfree(ports); 70153a5a1b3Sopenharmony_ci} 70253a5a1b3Sopenharmony_ci 70353a5a1b3Sopenharmony_cistatic void handle_get_active_port(DBusConnection *conn, DBusMessage *msg, void *userdata) { 70453a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 70553a5a1b3Sopenharmony_ci const char *active_port; 70653a5a1b3Sopenharmony_ci 70753a5a1b3Sopenharmony_ci pa_assert(conn); 70853a5a1b3Sopenharmony_ci pa_assert(msg); 70953a5a1b3Sopenharmony_ci pa_assert(d); 71053a5a1b3Sopenharmony_ci 71153a5a1b3Sopenharmony_ci if (!d->active_port) { 71253a5a1b3Sopenharmony_ci pa_assert(pa_hashmap_isempty(d->ports)); 71353a5a1b3Sopenharmony_ci 71453a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 71553a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 71653a5a1b3Sopenharmony_ci "The sink %s has no ports, and therefore there's no active port either.", d->sink->name); 71753a5a1b3Sopenharmony_ci else 71853a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 71953a5a1b3Sopenharmony_ci "The source %s has no ports, and therefore there's no active port either.", d->source->name); 72053a5a1b3Sopenharmony_ci return; 72153a5a1b3Sopenharmony_ci } 72253a5a1b3Sopenharmony_ci 72353a5a1b3Sopenharmony_ci active_port = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name)); 72453a5a1b3Sopenharmony_ci 72553a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &active_port); 72653a5a1b3Sopenharmony_ci} 72753a5a1b3Sopenharmony_ci 72853a5a1b3Sopenharmony_cistatic void handle_set_active_port(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { 72953a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 73053a5a1b3Sopenharmony_ci const char *new_active_path; 73153a5a1b3Sopenharmony_ci pa_dbusiface_device_port *port; 73253a5a1b3Sopenharmony_ci void *state; 73353a5a1b3Sopenharmony_ci pa_dbusiface_device_port *new_active = NULL; 73453a5a1b3Sopenharmony_ci int r; 73553a5a1b3Sopenharmony_ci 73653a5a1b3Sopenharmony_ci pa_assert(conn); 73753a5a1b3Sopenharmony_ci pa_assert(msg); 73853a5a1b3Sopenharmony_ci pa_assert(iter); 73953a5a1b3Sopenharmony_ci pa_assert(d); 74053a5a1b3Sopenharmony_ci 74153a5a1b3Sopenharmony_ci if (!d->active_port) { 74253a5a1b3Sopenharmony_ci pa_assert(pa_hashmap_isempty(d->ports)); 74353a5a1b3Sopenharmony_ci 74453a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 74553a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 74653a5a1b3Sopenharmony_ci "The sink %s has no ports, and therefore there's no active port either.", d->sink->name); 74753a5a1b3Sopenharmony_ci else 74853a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, 74953a5a1b3Sopenharmony_ci "The source %s has no ports, and therefore there's no active port either.", d->source->name); 75053a5a1b3Sopenharmony_ci return; 75153a5a1b3Sopenharmony_ci } 75253a5a1b3Sopenharmony_ci 75353a5a1b3Sopenharmony_ci dbus_message_iter_get_basic(iter, &new_active_path); 75453a5a1b3Sopenharmony_ci 75553a5a1b3Sopenharmony_ci PA_HASHMAP_FOREACH(port, d->ports, state) { 75653a5a1b3Sopenharmony_ci if (pa_streq(pa_dbusiface_device_port_get_path(port), new_active_path)) { 75753a5a1b3Sopenharmony_ci new_active = port; 75853a5a1b3Sopenharmony_ci break; 75953a5a1b3Sopenharmony_ci } 76053a5a1b3Sopenharmony_ci } 76153a5a1b3Sopenharmony_ci 76253a5a1b3Sopenharmony_ci if (!new_active) { 76353a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such port: %s", new_active_path); 76453a5a1b3Sopenharmony_ci return; 76553a5a1b3Sopenharmony_ci } 76653a5a1b3Sopenharmony_ci 76753a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) { 76853a5a1b3Sopenharmony_ci if ((r = pa_sink_set_port(d->sink, pa_dbusiface_device_port_get_name(new_active), true)) < 0) { 76953a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, 77053a5a1b3Sopenharmony_ci "Internal error in PulseAudio: pa_sink_set_port() failed with error code %i.", r); 77153a5a1b3Sopenharmony_ci return; 77253a5a1b3Sopenharmony_ci } 77353a5a1b3Sopenharmony_ci } else { 77453a5a1b3Sopenharmony_ci if ((r = pa_source_set_port(d->source, pa_dbusiface_device_port_get_name(new_active), true)) < 0) { 77553a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, 77653a5a1b3Sopenharmony_ci "Internal error in PulseAudio: pa_source_set_port() failed with error code %i.", r); 77753a5a1b3Sopenharmony_ci return; 77853a5a1b3Sopenharmony_ci } 77953a5a1b3Sopenharmony_ci } 78053a5a1b3Sopenharmony_ci 78153a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 78253a5a1b3Sopenharmony_ci} 78353a5a1b3Sopenharmony_ci 78453a5a1b3Sopenharmony_cistatic void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { 78553a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 78653a5a1b3Sopenharmony_ci 78753a5a1b3Sopenharmony_ci pa_assert(conn); 78853a5a1b3Sopenharmony_ci pa_assert(msg); 78953a5a1b3Sopenharmony_ci pa_assert(d); 79053a5a1b3Sopenharmony_ci 79153a5a1b3Sopenharmony_ci pa_dbus_send_proplist_variant_reply(conn, msg, d->proplist); 79253a5a1b3Sopenharmony_ci} 79353a5a1b3Sopenharmony_ci 79453a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { 79553a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 79653a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 79753a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 79853a5a1b3Sopenharmony_ci DBusMessageIter dict_iter; 79953a5a1b3Sopenharmony_ci dbus_uint32_t idx = 0; 80053a5a1b3Sopenharmony_ci const char *name = NULL; 80153a5a1b3Sopenharmony_ci const char *driver = NULL; 80253a5a1b3Sopenharmony_ci pa_module *owner_module = NULL; 80353a5a1b3Sopenharmony_ci const char *owner_module_path = NULL; 80453a5a1b3Sopenharmony_ci pa_card *card = NULL; 80553a5a1b3Sopenharmony_ci const char *card_path = NULL; 80653a5a1b3Sopenharmony_ci dbus_uint32_t sample_format = 0; 80753a5a1b3Sopenharmony_ci dbus_uint32_t sample_rate = 0; 80853a5a1b3Sopenharmony_ci pa_channel_map *channel_map = NULL; 80953a5a1b3Sopenharmony_ci dbus_uint32_t channels[PA_CHANNELS_MAX]; 81053a5a1b3Sopenharmony_ci dbus_uint32_t volume[PA_CHANNELS_MAX]; 81153a5a1b3Sopenharmony_ci dbus_bool_t has_flat_volume = FALSE; 81253a5a1b3Sopenharmony_ci dbus_bool_t has_convertible_to_decibel_volume = FALSE; 81353a5a1b3Sopenharmony_ci dbus_uint32_t base_volume = 0; 81453a5a1b3Sopenharmony_ci dbus_uint32_t volume_steps = 0; 81553a5a1b3Sopenharmony_ci dbus_bool_t has_hardware_volume = FALSE; 81653a5a1b3Sopenharmony_ci dbus_bool_t has_hardware_mute = FALSE; 81753a5a1b3Sopenharmony_ci dbus_uint64_t configured_latency = 0; 81853a5a1b3Sopenharmony_ci dbus_bool_t has_dynamic_latency = FALSE; 81953a5a1b3Sopenharmony_ci dbus_uint64_t latency = 0; 82053a5a1b3Sopenharmony_ci dbus_bool_t is_hardware_device = FALSE; 82153a5a1b3Sopenharmony_ci dbus_bool_t is_network_device = FALSE; 82253a5a1b3Sopenharmony_ci dbus_uint32_t state = 0; 82353a5a1b3Sopenharmony_ci const char **ports = NULL; 82453a5a1b3Sopenharmony_ci unsigned n_ports = 0; 82553a5a1b3Sopenharmony_ci const char *active_port = NULL; 82653a5a1b3Sopenharmony_ci unsigned i = 0; 82753a5a1b3Sopenharmony_ci 82853a5a1b3Sopenharmony_ci pa_assert(conn); 82953a5a1b3Sopenharmony_ci pa_assert(msg); 83053a5a1b3Sopenharmony_ci pa_assert(d); 83153a5a1b3Sopenharmony_ci 83253a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) { 83353a5a1b3Sopenharmony_ci idx = d->sink->index; 83453a5a1b3Sopenharmony_ci name = d->sink->name; 83553a5a1b3Sopenharmony_ci driver = d->sink->driver; 83653a5a1b3Sopenharmony_ci owner_module = d->sink->module; 83753a5a1b3Sopenharmony_ci card = d->sink->card; 83853a5a1b3Sopenharmony_ci sample_format = d->sink->sample_spec.format; 83953a5a1b3Sopenharmony_ci sample_rate = d->sink->sample_spec.rate; 84053a5a1b3Sopenharmony_ci channel_map = &d->sink->channel_map; 84153a5a1b3Sopenharmony_ci has_flat_volume = !!(d->sink->flags & PA_SINK_FLAT_VOLUME); 84253a5a1b3Sopenharmony_ci has_convertible_to_decibel_volume = !!(d->sink->flags & PA_SINK_DECIBEL_VOLUME); 84353a5a1b3Sopenharmony_ci base_volume = d->sink->base_volume; 84453a5a1b3Sopenharmony_ci volume_steps = d->sink->n_volume_steps; 84553a5a1b3Sopenharmony_ci has_hardware_volume = !!(d->sink->flags & PA_SINK_HW_VOLUME_CTRL); 84653a5a1b3Sopenharmony_ci has_hardware_mute = !!(d->sink->flags & PA_SINK_HW_MUTE_CTRL); 84753a5a1b3Sopenharmony_ci configured_latency = pa_sink_get_requested_latency(d->sink); 84853a5a1b3Sopenharmony_ci has_dynamic_latency = !!(d->sink->flags & PA_SINK_DYNAMIC_LATENCY); 84953a5a1b3Sopenharmony_ci latency = pa_sink_get_latency(d->sink); 85053a5a1b3Sopenharmony_ci is_hardware_device = !!(d->sink->flags & PA_SINK_HARDWARE); 85153a5a1b3Sopenharmony_ci is_network_device = !!(d->sink->flags & PA_SINK_NETWORK); 85253a5a1b3Sopenharmony_ci state = d->sink->state; 85353a5a1b3Sopenharmony_ci } else { 85453a5a1b3Sopenharmony_ci idx = d->source->index; 85553a5a1b3Sopenharmony_ci name = d->source->name; 85653a5a1b3Sopenharmony_ci driver = d->source->driver; 85753a5a1b3Sopenharmony_ci owner_module = d->source->module; 85853a5a1b3Sopenharmony_ci card = d->source->card; 85953a5a1b3Sopenharmony_ci sample_format = d->source->sample_spec.format; 86053a5a1b3Sopenharmony_ci sample_rate = d->source->sample_spec.rate; 86153a5a1b3Sopenharmony_ci channel_map = &d->source->channel_map; 86253a5a1b3Sopenharmony_ci has_flat_volume = FALSE; 86353a5a1b3Sopenharmony_ci has_convertible_to_decibel_volume = !!(d->source->flags & PA_SOURCE_DECIBEL_VOLUME); 86453a5a1b3Sopenharmony_ci base_volume = d->source->base_volume; 86553a5a1b3Sopenharmony_ci volume_steps = d->source->n_volume_steps; 86653a5a1b3Sopenharmony_ci has_hardware_volume = !!(d->source->flags & PA_SOURCE_HW_VOLUME_CTRL); 86753a5a1b3Sopenharmony_ci has_hardware_mute = !!(d->source->flags & PA_SOURCE_HW_MUTE_CTRL); 86853a5a1b3Sopenharmony_ci configured_latency = pa_source_get_requested_latency(d->source); 86953a5a1b3Sopenharmony_ci has_dynamic_latency = !!(d->source->flags & PA_SOURCE_DYNAMIC_LATENCY); 87053a5a1b3Sopenharmony_ci latency = pa_source_get_latency(d->source); 87153a5a1b3Sopenharmony_ci is_hardware_device = !!(d->source->flags & PA_SOURCE_HARDWARE); 87253a5a1b3Sopenharmony_ci is_network_device = !!(d->source->flags & PA_SOURCE_NETWORK); 87353a5a1b3Sopenharmony_ci state = d->source->state; 87453a5a1b3Sopenharmony_ci } 87553a5a1b3Sopenharmony_ci if (owner_module) 87653a5a1b3Sopenharmony_ci owner_module_path = pa_dbusiface_core_get_module_path(d->core, owner_module); 87753a5a1b3Sopenharmony_ci if (card) 87853a5a1b3Sopenharmony_ci card_path = pa_dbusiface_core_get_card_path(d->core, card); 87953a5a1b3Sopenharmony_ci for (i = 0; i < channel_map->channels; ++i) 88053a5a1b3Sopenharmony_ci channels[i] = channel_map->map[i]; 88153a5a1b3Sopenharmony_ci for (i = 0; i < d->volume.channels; ++i) 88253a5a1b3Sopenharmony_ci volume[i] = d->volume.values[i]; 88353a5a1b3Sopenharmony_ci ports = get_ports(d, &n_ports); 88453a5a1b3Sopenharmony_ci if (d->active_port) 88553a5a1b3Sopenharmony_ci active_port = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name)); 88653a5a1b3Sopenharmony_ci 88753a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(msg))); 88853a5a1b3Sopenharmony_ci 88953a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 89053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); 89153a5a1b3Sopenharmony_ci 89253a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); 89353a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &name); 89453a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &driver); 89553a5a1b3Sopenharmony_ci 89653a5a1b3Sopenharmony_ci if (owner_module) 89753a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module_path); 89853a5a1b3Sopenharmony_ci 89953a5a1b3Sopenharmony_ci if (card) 90053a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CARD].property_name, DBUS_TYPE_OBJECT_PATH, &card_path); 90153a5a1b3Sopenharmony_ci 90253a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format); 90353a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &sample_rate); 90453a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels); 90553a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, d->volume.channels); 90653a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_FLAT_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_flat_volume); 90753a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_convertible_to_decibel_volume); 90853a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BASE_VOLUME].property_name, DBUS_TYPE_UINT32, &base_volume); 90953a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME_STEPS].property_name, DBUS_TYPE_UINT32, &volume_steps); 91053a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &d->mute); 91153a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_HARDWARE_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_hardware_volume); 91253a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_HARDWARE_MUTE].property_name, DBUS_TYPE_BOOLEAN, &has_hardware_mute); 91353a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CONFIGURED_LATENCY].property_name, DBUS_TYPE_UINT64, &configured_latency); 91453a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY].property_name, DBUS_TYPE_BOOLEAN, &has_dynamic_latency); 91553a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_LATENCY].property_name, DBUS_TYPE_UINT64, &latency); 91653a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_HARDWARE_DEVICE].property_name, DBUS_TYPE_BOOLEAN, &is_hardware_device); 91753a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_NETWORK_DEVICE].property_name, DBUS_TYPE_BOOLEAN, &is_network_device); 91853a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_STATE].property_name, DBUS_TYPE_UINT32, &state); 91953a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PORTS].property_name, DBUS_TYPE_OBJECT_PATH, ports, n_ports); 92053a5a1b3Sopenharmony_ci 92153a5a1b3Sopenharmony_ci if (active_port) 92253a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACTIVE_PORT].property_name, DBUS_TYPE_OBJECT_PATH, &active_port); 92353a5a1b3Sopenharmony_ci 92453a5a1b3Sopenharmony_ci pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, d->proplist); 92553a5a1b3Sopenharmony_ci 92653a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); 92753a5a1b3Sopenharmony_ci 92853a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(conn, reply, NULL)); 92953a5a1b3Sopenharmony_ci 93053a5a1b3Sopenharmony_ci dbus_message_unref(reply); 93153a5a1b3Sopenharmony_ci 93253a5a1b3Sopenharmony_ci pa_xfree(ports); 93353a5a1b3Sopenharmony_ci} 93453a5a1b3Sopenharmony_ci 93553a5a1b3Sopenharmony_cistatic void handle_suspend(DBusConnection *conn, DBusMessage *msg, void *userdata) { 93653a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 93753a5a1b3Sopenharmony_ci dbus_bool_t suspend = FALSE; 93853a5a1b3Sopenharmony_ci pa_client *client; 93953a5a1b3Sopenharmony_ci 94053a5a1b3Sopenharmony_ci pa_assert(conn); 94153a5a1b3Sopenharmony_ci pa_assert(msg); 94253a5a1b3Sopenharmony_ci pa_assert(d); 94353a5a1b3Sopenharmony_ci 94453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &suspend, DBUS_TYPE_INVALID)); 94553a5a1b3Sopenharmony_ci pa_assert_se(client = pa_dbus_protocol_get_client(d->dbus_protocol, conn)); 94653a5a1b3Sopenharmony_ci 94753a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) { 94853a5a1b3Sopenharmony_ci pa_log_debug("%s sink %s requested by client %" PRIu32 ".", suspend ? "Suspending" : "Resuming", d->sink->name, client->index); 94953a5a1b3Sopenharmony_ci 95053a5a1b3Sopenharmony_ci if (pa_sink_suspend(d->sink, suspend, PA_SUSPEND_USER) < 0) { 95153a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_sink_suspend() failed."); 95253a5a1b3Sopenharmony_ci return; 95353a5a1b3Sopenharmony_ci } 95453a5a1b3Sopenharmony_ci 95553a5a1b3Sopenharmony_ci } else { 95653a5a1b3Sopenharmony_ci pa_log_debug("%s source %s requested by client %" PRIu32 ".", suspend ? "Suspending" : "Resuming", d->source->name, client->index); 95753a5a1b3Sopenharmony_ci 95853a5a1b3Sopenharmony_ci if (pa_source_suspend(d->source, suspend, PA_SUSPEND_USER) < 0) { 95953a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_source_suspend() failed."); 96053a5a1b3Sopenharmony_ci return; 96153a5a1b3Sopenharmony_ci } 96253a5a1b3Sopenharmony_ci } 96353a5a1b3Sopenharmony_ci 96453a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 96553a5a1b3Sopenharmony_ci} 96653a5a1b3Sopenharmony_ci 96753a5a1b3Sopenharmony_cistatic void handle_get_port_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { 96853a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 96953a5a1b3Sopenharmony_ci const char *port_name = NULL; 97053a5a1b3Sopenharmony_ci pa_dbusiface_device_port *port = NULL; 97153a5a1b3Sopenharmony_ci const char *port_path = NULL; 97253a5a1b3Sopenharmony_ci 97353a5a1b3Sopenharmony_ci pa_assert(conn); 97453a5a1b3Sopenharmony_ci pa_assert(msg); 97553a5a1b3Sopenharmony_ci pa_assert(d); 97653a5a1b3Sopenharmony_ci 97753a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &port_name, DBUS_TYPE_INVALID)); 97853a5a1b3Sopenharmony_ci 97953a5a1b3Sopenharmony_ci if (!(port = pa_hashmap_get(d->ports, port_name))) { 98053a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 98153a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, 98253a5a1b3Sopenharmony_ci "%s: No such port on sink %s.", port_name, d->sink->name); 98353a5a1b3Sopenharmony_ci else 98453a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, 98553a5a1b3Sopenharmony_ci "%s: No such port on source %s.", port_name, d->source->name); 98653a5a1b3Sopenharmony_ci return; 98753a5a1b3Sopenharmony_ci } 98853a5a1b3Sopenharmony_ci 98953a5a1b3Sopenharmony_ci port_path = pa_dbusiface_device_port_get_path(port); 99053a5a1b3Sopenharmony_ci 99153a5a1b3Sopenharmony_ci pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &port_path); 99253a5a1b3Sopenharmony_ci} 99353a5a1b3Sopenharmony_ci 99453a5a1b3Sopenharmony_cistatic void handle_sink_get_monitor_source(DBusConnection *conn, DBusMessage *msg, void *userdata) { 99553a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 99653a5a1b3Sopenharmony_ci const char *monitor_source = NULL; 99753a5a1b3Sopenharmony_ci 99853a5a1b3Sopenharmony_ci pa_assert(conn); 99953a5a1b3Sopenharmony_ci pa_assert(msg); 100053a5a1b3Sopenharmony_ci pa_assert(d); 100153a5a1b3Sopenharmony_ci pa_assert(d->type == PA_DEVICE_TYPE_SINK); 100253a5a1b3Sopenharmony_ci 100353a5a1b3Sopenharmony_ci monitor_source = pa_dbusiface_core_get_source_path(d->core, d->sink->monitor_source); 100453a5a1b3Sopenharmony_ci 100553a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &monitor_source); 100653a5a1b3Sopenharmony_ci} 100753a5a1b3Sopenharmony_ci 100853a5a1b3Sopenharmony_cistatic void handle_sink_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { 100953a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 101053a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 101153a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 101253a5a1b3Sopenharmony_ci DBusMessageIter dict_iter; 101353a5a1b3Sopenharmony_ci const char *monitor_source = NULL; 101453a5a1b3Sopenharmony_ci 101553a5a1b3Sopenharmony_ci pa_assert(conn); 101653a5a1b3Sopenharmony_ci pa_assert(msg); 101753a5a1b3Sopenharmony_ci pa_assert(d); 101853a5a1b3Sopenharmony_ci pa_assert(d->type == PA_DEVICE_TYPE_SINK); 101953a5a1b3Sopenharmony_ci 102053a5a1b3Sopenharmony_ci monitor_source = pa_dbusiface_core_get_source_path(d->core, d->sink->monitor_source); 102153a5a1b3Sopenharmony_ci 102253a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(msg))); 102353a5a1b3Sopenharmony_ci 102453a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 102553a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); 102653a5a1b3Sopenharmony_ci 102753a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[SINK_PROPERTY_HANDLER_MONITOR_SOURCE].property_name, DBUS_TYPE_OBJECT_PATH, &monitor_source); 102853a5a1b3Sopenharmony_ci 102953a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); 103053a5a1b3Sopenharmony_ci 103153a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(conn, reply, NULL)); 103253a5a1b3Sopenharmony_ci 103353a5a1b3Sopenharmony_ci dbus_message_unref(reply); 103453a5a1b3Sopenharmony_ci} 103553a5a1b3Sopenharmony_ci 103653a5a1b3Sopenharmony_cistatic void handle_source_get_monitor_of_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) { 103753a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 103853a5a1b3Sopenharmony_ci const char *monitor_of_sink = NULL; 103953a5a1b3Sopenharmony_ci 104053a5a1b3Sopenharmony_ci pa_assert(conn); 104153a5a1b3Sopenharmony_ci pa_assert(msg); 104253a5a1b3Sopenharmony_ci pa_assert(d); 104353a5a1b3Sopenharmony_ci pa_assert(d->type == PA_DEVICE_TYPE_SOURCE); 104453a5a1b3Sopenharmony_ci 104553a5a1b3Sopenharmony_ci if (!d->source->monitor_of) { 104653a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Source %s is not a monitor source.", d->source->name); 104753a5a1b3Sopenharmony_ci return; 104853a5a1b3Sopenharmony_ci } 104953a5a1b3Sopenharmony_ci 105053a5a1b3Sopenharmony_ci monitor_of_sink = pa_dbusiface_core_get_sink_path(d->core, d->source->monitor_of); 105153a5a1b3Sopenharmony_ci 105253a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &monitor_of_sink); 105353a5a1b3Sopenharmony_ci} 105453a5a1b3Sopenharmony_ci 105553a5a1b3Sopenharmony_cistatic void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { 105653a5a1b3Sopenharmony_ci pa_dbusiface_device *d = userdata; 105753a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 105853a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 105953a5a1b3Sopenharmony_ci DBusMessageIter dict_iter; 106053a5a1b3Sopenharmony_ci const char *monitor_of_sink = NULL; 106153a5a1b3Sopenharmony_ci 106253a5a1b3Sopenharmony_ci pa_assert(conn); 106353a5a1b3Sopenharmony_ci pa_assert(msg); 106453a5a1b3Sopenharmony_ci pa_assert(d); 106553a5a1b3Sopenharmony_ci pa_assert(d->type == PA_DEVICE_TYPE_SOURCE); 106653a5a1b3Sopenharmony_ci 106753a5a1b3Sopenharmony_ci if (d->source->monitor_of) 106853a5a1b3Sopenharmony_ci monitor_of_sink = pa_dbusiface_core_get_sink_path(d->core, d->source->monitor_of); 106953a5a1b3Sopenharmony_ci 107053a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(msg))); 107153a5a1b3Sopenharmony_ci 107253a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 107353a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); 107453a5a1b3Sopenharmony_ci 107553a5a1b3Sopenharmony_ci if (monitor_of_sink) 107653a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK].property_name, DBUS_TYPE_OBJECT_PATH, &monitor_of_sink); 107753a5a1b3Sopenharmony_ci 107853a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); 107953a5a1b3Sopenharmony_ci 108053a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(conn, reply, NULL)); 108153a5a1b3Sopenharmony_ci 108253a5a1b3Sopenharmony_ci dbus_message_unref(reply); 108353a5a1b3Sopenharmony_ci} 108453a5a1b3Sopenharmony_ci 108553a5a1b3Sopenharmony_cistatic pa_hook_result_t volume_changed_cb(void *hook_data, void *call_data, void *slot_data) { 108653a5a1b3Sopenharmony_ci pa_dbusiface_device *d = slot_data; 108753a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 108853a5a1b3Sopenharmony_ci const pa_cvolume *new_volume = NULL; 108953a5a1b3Sopenharmony_ci unsigned i = 0; 109053a5a1b3Sopenharmony_ci 109153a5a1b3Sopenharmony_ci if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || 109253a5a1b3Sopenharmony_ci (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) 109353a5a1b3Sopenharmony_ci return PA_HOOK_OK; 109453a5a1b3Sopenharmony_ci 109553a5a1b3Sopenharmony_ci new_volume = (d->type == PA_DEVICE_TYPE_SINK) 109653a5a1b3Sopenharmony_ci ? pa_sink_get_volume(d->sink, false) 109753a5a1b3Sopenharmony_ci : pa_source_get_volume(d->source, false); 109853a5a1b3Sopenharmony_ci 109953a5a1b3Sopenharmony_ci if (!pa_cvolume_equal(&d->volume, new_volume)) { 110053a5a1b3Sopenharmony_ci dbus_uint32_t volume[PA_CHANNELS_MAX]; 110153a5a1b3Sopenharmony_ci dbus_uint32_t *volume_ptr = volume; 110253a5a1b3Sopenharmony_ci 110353a5a1b3Sopenharmony_ci d->volume = *new_volume; 110453a5a1b3Sopenharmony_ci 110553a5a1b3Sopenharmony_ci for (i = 0; i < d->volume.channels; ++i) 110653a5a1b3Sopenharmony_ci volume[i] = d->volume.values[i]; 110753a5a1b3Sopenharmony_ci 110853a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(d->path, 110953a5a1b3Sopenharmony_ci PA_DBUSIFACE_DEVICE_INTERFACE, 111053a5a1b3Sopenharmony_ci signals[SIGNAL_VOLUME_UPDATED].name)); 111153a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, 111253a5a1b3Sopenharmony_ci DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, d->volume.channels, 111353a5a1b3Sopenharmony_ci DBUS_TYPE_INVALID)); 111453a5a1b3Sopenharmony_ci 111553a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); 111653a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 111753a5a1b3Sopenharmony_ci } 111853a5a1b3Sopenharmony_ci 111953a5a1b3Sopenharmony_ci return PA_HOOK_OK; 112053a5a1b3Sopenharmony_ci} 112153a5a1b3Sopenharmony_ci 112253a5a1b3Sopenharmony_cistatic pa_hook_result_t mute_changed_cb(void *hook_data, void *call_data, void *slot_data) { 112353a5a1b3Sopenharmony_ci pa_dbusiface_device *d = slot_data; 112453a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 112553a5a1b3Sopenharmony_ci bool new_mute = false; 112653a5a1b3Sopenharmony_ci 112753a5a1b3Sopenharmony_ci if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || 112853a5a1b3Sopenharmony_ci (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) 112953a5a1b3Sopenharmony_ci return PA_HOOK_OK; 113053a5a1b3Sopenharmony_ci 113153a5a1b3Sopenharmony_ci new_mute = (d->type == PA_DEVICE_TYPE_SINK) 113253a5a1b3Sopenharmony_ci ? pa_sink_get_mute(d->sink, false) 113353a5a1b3Sopenharmony_ci : pa_source_get_mute(d->source, false); 113453a5a1b3Sopenharmony_ci 113553a5a1b3Sopenharmony_ci if (d->mute != new_mute) { 113653a5a1b3Sopenharmony_ci d->mute = new_mute; 113753a5a1b3Sopenharmony_ci 113853a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(d->path, 113953a5a1b3Sopenharmony_ci PA_DBUSIFACE_DEVICE_INTERFACE, 114053a5a1b3Sopenharmony_ci signals[SIGNAL_MUTE_UPDATED].name)); 114153a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID)); 114253a5a1b3Sopenharmony_ci 114353a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); 114453a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 114553a5a1b3Sopenharmony_ci } 114653a5a1b3Sopenharmony_ci 114753a5a1b3Sopenharmony_ci return PA_HOOK_OK; 114853a5a1b3Sopenharmony_ci} 114953a5a1b3Sopenharmony_ci 115053a5a1b3Sopenharmony_cistatic pa_hook_result_t state_changed_cb(void *hook_data, void *call_data, void *slot_data) { 115153a5a1b3Sopenharmony_ci pa_dbusiface_device *d = slot_data; 115253a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 115353a5a1b3Sopenharmony_ci pa_sink_state_t new_sink_state = 0; 115453a5a1b3Sopenharmony_ci pa_source_state_t new_source_state = 0; 115553a5a1b3Sopenharmony_ci 115653a5a1b3Sopenharmony_ci if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || 115753a5a1b3Sopenharmony_ci (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) 115853a5a1b3Sopenharmony_ci return PA_HOOK_OK; 115953a5a1b3Sopenharmony_ci 116053a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 116153a5a1b3Sopenharmony_ci new_sink_state = d->sink->state; 116253a5a1b3Sopenharmony_ci else 116353a5a1b3Sopenharmony_ci new_source_state = d->source->state; 116453a5a1b3Sopenharmony_ci 116553a5a1b3Sopenharmony_ci if ((d->type == PA_DEVICE_TYPE_SINK && d->sink_state != new_sink_state) 116653a5a1b3Sopenharmony_ci || (d->type == PA_DEVICE_TYPE_SOURCE && d->source_state != new_source_state)) { 116753a5a1b3Sopenharmony_ci dbus_uint32_t state = 0; 116853a5a1b3Sopenharmony_ci 116953a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) 117053a5a1b3Sopenharmony_ci d->sink_state = new_sink_state; 117153a5a1b3Sopenharmony_ci else 117253a5a1b3Sopenharmony_ci d->source_state = new_source_state; 117353a5a1b3Sopenharmony_ci 117453a5a1b3Sopenharmony_ci state = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink_state : d->source_state; 117553a5a1b3Sopenharmony_ci 117653a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(d->path, 117753a5a1b3Sopenharmony_ci PA_DBUSIFACE_DEVICE_INTERFACE, 117853a5a1b3Sopenharmony_ci signals[SIGNAL_STATE_UPDATED].name)); 117953a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID)); 118053a5a1b3Sopenharmony_ci 118153a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); 118253a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 118353a5a1b3Sopenharmony_ci } 118453a5a1b3Sopenharmony_ci 118553a5a1b3Sopenharmony_ci return PA_HOOK_OK; 118653a5a1b3Sopenharmony_ci} 118753a5a1b3Sopenharmony_ci 118853a5a1b3Sopenharmony_cistatic pa_hook_result_t port_changed_cb(void *hook_data, void *call_data, void *slot_data) { 118953a5a1b3Sopenharmony_ci pa_dbusiface_device *d = slot_data; 119053a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 119153a5a1b3Sopenharmony_ci pa_device_port *new_active_port = NULL; 119253a5a1b3Sopenharmony_ci 119353a5a1b3Sopenharmony_ci if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || 119453a5a1b3Sopenharmony_ci (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) 119553a5a1b3Sopenharmony_ci return PA_HOOK_OK; 119653a5a1b3Sopenharmony_ci 119753a5a1b3Sopenharmony_ci new_active_port = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->active_port : d->source->active_port; 119853a5a1b3Sopenharmony_ci 119953a5a1b3Sopenharmony_ci if (d->active_port != new_active_port) { 120053a5a1b3Sopenharmony_ci const char *object_path = NULL; 120153a5a1b3Sopenharmony_ci 120253a5a1b3Sopenharmony_ci d->active_port = new_active_port; 120353a5a1b3Sopenharmony_ci object_path = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name)); 120453a5a1b3Sopenharmony_ci 120553a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(d->path, 120653a5a1b3Sopenharmony_ci PA_DBUSIFACE_DEVICE_INTERFACE, 120753a5a1b3Sopenharmony_ci signals[SIGNAL_ACTIVE_PORT_UPDATED].name)); 120853a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); 120953a5a1b3Sopenharmony_ci 121053a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); 121153a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 121253a5a1b3Sopenharmony_ci } 121353a5a1b3Sopenharmony_ci 121453a5a1b3Sopenharmony_ci return PA_HOOK_OK; 121553a5a1b3Sopenharmony_ci} 121653a5a1b3Sopenharmony_ci 121753a5a1b3Sopenharmony_cistatic pa_hook_result_t proplist_changed_cb(void *hook_data, void *call_data, void *slot_data) { 121853a5a1b3Sopenharmony_ci pa_dbusiface_device *d = slot_data; 121953a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 122053a5a1b3Sopenharmony_ci pa_proplist *new_proplist = NULL; 122153a5a1b3Sopenharmony_ci 122253a5a1b3Sopenharmony_ci if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || 122353a5a1b3Sopenharmony_ci (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) 122453a5a1b3Sopenharmony_ci return PA_HOOK_OK; 122553a5a1b3Sopenharmony_ci 122653a5a1b3Sopenharmony_ci new_proplist = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->proplist : d->source->proplist; 122753a5a1b3Sopenharmony_ci 122853a5a1b3Sopenharmony_ci if (!pa_proplist_equal(d->proplist, new_proplist)) { 122953a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 123053a5a1b3Sopenharmony_ci 123153a5a1b3Sopenharmony_ci pa_proplist_update(d->proplist, PA_UPDATE_SET, new_proplist); 123253a5a1b3Sopenharmony_ci 123353a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(d->path, 123453a5a1b3Sopenharmony_ci PA_DBUSIFACE_DEVICE_INTERFACE, 123553a5a1b3Sopenharmony_ci signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); 123653a5a1b3Sopenharmony_ci dbus_message_iter_init_append(signal_msg, &msg_iter); 123753a5a1b3Sopenharmony_ci pa_dbus_append_proplist(&msg_iter, d->proplist); 123853a5a1b3Sopenharmony_ci 123953a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); 124053a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 124153a5a1b3Sopenharmony_ci } 124253a5a1b3Sopenharmony_ci 124353a5a1b3Sopenharmony_ci return PA_HOOK_OK; 124453a5a1b3Sopenharmony_ci} 124553a5a1b3Sopenharmony_ci 124653a5a1b3Sopenharmony_cipa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_sink *sink) { 124753a5a1b3Sopenharmony_ci pa_dbusiface_device *d = NULL; 124853a5a1b3Sopenharmony_ci pa_device_port *port; 124953a5a1b3Sopenharmony_ci void *state; 125053a5a1b3Sopenharmony_ci 125153a5a1b3Sopenharmony_ci pa_assert(core); 125253a5a1b3Sopenharmony_ci pa_assert(sink); 125353a5a1b3Sopenharmony_ci 125453a5a1b3Sopenharmony_ci d = pa_xnew0(pa_dbusiface_device, 1); 125553a5a1b3Sopenharmony_ci d->core = core; 125653a5a1b3Sopenharmony_ci d->sink = pa_sink_ref(sink); 125753a5a1b3Sopenharmony_ci d->type = PA_DEVICE_TYPE_SINK; 125853a5a1b3Sopenharmony_ci d->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, SINK_OBJECT_NAME, sink->index); 125953a5a1b3Sopenharmony_ci d->volume = *pa_sink_get_volume(sink, false); 126053a5a1b3Sopenharmony_ci d->mute = pa_sink_get_mute(sink, false); 126153a5a1b3Sopenharmony_ci d->sink_state = sink->state; 126253a5a1b3Sopenharmony_ci d->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_device_port_free); 126353a5a1b3Sopenharmony_ci d->next_port_index = 0; 126453a5a1b3Sopenharmony_ci d->active_port = sink->active_port; 126553a5a1b3Sopenharmony_ci d->proplist = pa_proplist_copy(sink->proplist); 126653a5a1b3Sopenharmony_ci d->dbus_protocol = pa_dbus_protocol_get(sink->core); 126753a5a1b3Sopenharmony_ci d->volume_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], 126853a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, volume_changed_cb, d); 126953a5a1b3Sopenharmony_ci d->mute_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_MUTE_CHANGED], 127053a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, mute_changed_cb, d); 127153a5a1b3Sopenharmony_ci d->state_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], 127253a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, state_changed_cb, d); 127353a5a1b3Sopenharmony_ci d->port_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], 127453a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, port_changed_cb, d); 127553a5a1b3Sopenharmony_ci d->proplist_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], 127653a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, proplist_changed_cb, d); 127753a5a1b3Sopenharmony_ci 127853a5a1b3Sopenharmony_ci PA_HASHMAP_FOREACH(port, sink->ports, state) { 127953a5a1b3Sopenharmony_ci pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, sink->core, port, d->next_port_index++); 128053a5a1b3Sopenharmony_ci pa_hashmap_put(d->ports, (char *) pa_dbusiface_device_port_get_name(p), p); 128153a5a1b3Sopenharmony_ci } 128253a5a1b3Sopenharmony_ci 128353a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0); 128453a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &sink_interface_info, d) >= 0); 128553a5a1b3Sopenharmony_ci 128653a5a1b3Sopenharmony_ci return d; 128753a5a1b3Sopenharmony_ci} 128853a5a1b3Sopenharmony_ci 128953a5a1b3Sopenharmony_cipa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_source *source) { 129053a5a1b3Sopenharmony_ci pa_dbusiface_device *d = NULL; 129153a5a1b3Sopenharmony_ci pa_device_port *port; 129253a5a1b3Sopenharmony_ci void *state; 129353a5a1b3Sopenharmony_ci 129453a5a1b3Sopenharmony_ci pa_assert(core); 129553a5a1b3Sopenharmony_ci pa_assert(source); 129653a5a1b3Sopenharmony_ci 129753a5a1b3Sopenharmony_ci d = pa_xnew0(pa_dbusiface_device, 1); 129853a5a1b3Sopenharmony_ci d->core = core; 129953a5a1b3Sopenharmony_ci d->source = pa_source_ref(source); 130053a5a1b3Sopenharmony_ci d->type = PA_DEVICE_TYPE_SOURCE; 130153a5a1b3Sopenharmony_ci d->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, SOURCE_OBJECT_NAME, source->index); 130253a5a1b3Sopenharmony_ci d->volume = *pa_source_get_volume(source, false); 130353a5a1b3Sopenharmony_ci d->mute = pa_source_get_mute(source, false); 130453a5a1b3Sopenharmony_ci d->source_state = source->state; 130553a5a1b3Sopenharmony_ci d->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_device_port_free); 130653a5a1b3Sopenharmony_ci d->next_port_index = 0; 130753a5a1b3Sopenharmony_ci d->active_port = source->active_port; 130853a5a1b3Sopenharmony_ci d->proplist = pa_proplist_copy(source->proplist); 130953a5a1b3Sopenharmony_ci d->dbus_protocol = pa_dbus_protocol_get(source->core); 131053a5a1b3Sopenharmony_ci d->volume_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], 131153a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, volume_changed_cb, d); 131253a5a1b3Sopenharmony_ci d->mute_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_MUTE_CHANGED], 131353a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, mute_changed_cb, d); 131453a5a1b3Sopenharmony_ci d->state_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], 131553a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, state_changed_cb, d); 131653a5a1b3Sopenharmony_ci d->port_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED], 131753a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, port_changed_cb, d); 131853a5a1b3Sopenharmony_ci d->proplist_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], 131953a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, proplist_changed_cb, d); 132053a5a1b3Sopenharmony_ci 132153a5a1b3Sopenharmony_ci PA_HASHMAP_FOREACH(port, source->ports, state) { 132253a5a1b3Sopenharmony_ci pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, source->core, port, d->next_port_index++); 132353a5a1b3Sopenharmony_ci pa_hashmap_put(d->ports, (char *) pa_dbusiface_device_port_get_name(p), p); 132453a5a1b3Sopenharmony_ci } 132553a5a1b3Sopenharmony_ci 132653a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0); 132753a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &source_interface_info, d) >= 0); 132853a5a1b3Sopenharmony_ci 132953a5a1b3Sopenharmony_ci return d; 133053a5a1b3Sopenharmony_ci} 133153a5a1b3Sopenharmony_ci 133253a5a1b3Sopenharmony_civoid pa_dbusiface_device_free(pa_dbusiface_device *d) { 133353a5a1b3Sopenharmony_ci pa_assert(d); 133453a5a1b3Sopenharmony_ci 133553a5a1b3Sopenharmony_ci pa_hook_slot_free(d->volume_changed_slot); 133653a5a1b3Sopenharmony_ci pa_hook_slot_free(d->mute_changed_slot); 133753a5a1b3Sopenharmony_ci pa_hook_slot_free(d->state_changed_slot); 133853a5a1b3Sopenharmony_ci pa_hook_slot_free(d->port_changed_slot); 133953a5a1b3Sopenharmony_ci pa_hook_slot_free(d->proplist_changed_slot); 134053a5a1b3Sopenharmony_ci 134153a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, device_interface_info.name) >= 0); 134253a5a1b3Sopenharmony_ci 134353a5a1b3Sopenharmony_ci if (d->type == PA_DEVICE_TYPE_SINK) { 134453a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, sink_interface_info.name) >= 0); 134553a5a1b3Sopenharmony_ci pa_sink_unref(d->sink); 134653a5a1b3Sopenharmony_ci 134753a5a1b3Sopenharmony_ci } else { 134853a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, source_interface_info.name) >= 0); 134953a5a1b3Sopenharmony_ci pa_source_unref(d->source); 135053a5a1b3Sopenharmony_ci } 135153a5a1b3Sopenharmony_ci pa_hashmap_free(d->ports); 135253a5a1b3Sopenharmony_ci pa_proplist_free(d->proplist); 135353a5a1b3Sopenharmony_ci pa_dbus_protocol_unref(d->dbus_protocol); 135453a5a1b3Sopenharmony_ci 135553a5a1b3Sopenharmony_ci pa_xfree(d->path); 135653a5a1b3Sopenharmony_ci pa_xfree(d); 135753a5a1b3Sopenharmony_ci} 135853a5a1b3Sopenharmony_ci 135953a5a1b3Sopenharmony_ciconst char *pa_dbusiface_device_get_path(pa_dbusiface_device *d) { 136053a5a1b3Sopenharmony_ci pa_assert(d); 136153a5a1b3Sopenharmony_ci 136253a5a1b3Sopenharmony_ci return d->path; 136353a5a1b3Sopenharmony_ci} 136453a5a1b3Sopenharmony_ci 136553a5a1b3Sopenharmony_cipa_sink *pa_dbusiface_device_get_sink(pa_dbusiface_device *d) { 136653a5a1b3Sopenharmony_ci pa_assert(d); 136753a5a1b3Sopenharmony_ci pa_assert(d->type == PA_DEVICE_TYPE_SINK); 136853a5a1b3Sopenharmony_ci 136953a5a1b3Sopenharmony_ci return d->sink; 137053a5a1b3Sopenharmony_ci} 137153a5a1b3Sopenharmony_ci 137253a5a1b3Sopenharmony_cipa_source *pa_dbusiface_device_get_source(pa_dbusiface_device *d) { 137353a5a1b3Sopenharmony_ci pa_assert(d); 137453a5a1b3Sopenharmony_ci pa_assert(d->type == PA_DEVICE_TYPE_SOURCE); 137553a5a1b3Sopenharmony_ci 137653a5a1b3Sopenharmony_ci return d->source; 137753a5a1b3Sopenharmony_ci} 1378