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