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 <ctype.h>
2553a5a1b3Sopenharmony_ci
2653a5a1b3Sopenharmony_ci#include <dbus/dbus.h>
2753a5a1b3Sopenharmony_ci
2853a5a1b3Sopenharmony_ci#include <pulse/utf8.h>
2953a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h>
3053a5a1b3Sopenharmony_ci
3153a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h>
3253a5a1b3Sopenharmony_ci#include <pulsecore/dbus-util.h>
3353a5a1b3Sopenharmony_ci#include <pulsecore/macro.h>
3453a5a1b3Sopenharmony_ci#include <pulsecore/namereg.h>
3553a5a1b3Sopenharmony_ci#include <pulsecore/protocol-dbus.h>
3653a5a1b3Sopenharmony_ci#include <pulsecore/socket-util.h>
3753a5a1b3Sopenharmony_ci#include <pulsecore/strbuf.h>
3853a5a1b3Sopenharmony_ci
3953a5a1b3Sopenharmony_ci#include "iface-card.h"
4053a5a1b3Sopenharmony_ci#include "iface-client.h"
4153a5a1b3Sopenharmony_ci#include "iface-device.h"
4253a5a1b3Sopenharmony_ci#include "iface-memstats.h"
4353a5a1b3Sopenharmony_ci#include "iface-module.h"
4453a5a1b3Sopenharmony_ci#include "iface-sample.h"
4553a5a1b3Sopenharmony_ci#include "iface-stream.h"
4653a5a1b3Sopenharmony_ci
4753a5a1b3Sopenharmony_ci#include "iface-core.h"
4853a5a1b3Sopenharmony_ci
4953a5a1b3Sopenharmony_ci#define INTERFACE_REVISION 0
5053a5a1b3Sopenharmony_ci
5153a5a1b3Sopenharmony_cistatic void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata);
5253a5a1b3Sopenharmony_cistatic void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
5353a5a1b3Sopenharmony_cistatic void handle_get_version(DBusConnection *conn, DBusMessage *msg, void *userdata);
5453a5a1b3Sopenharmony_cistatic void handle_get_is_local(DBusConnection *conn, DBusMessage *msg, void *userdata);
5553a5a1b3Sopenharmony_cistatic void handle_get_username(DBusConnection *conn, DBusMessage *msg, void *userdata);
5653a5a1b3Sopenharmony_cistatic void handle_get_hostname(DBusConnection *conn, DBusMessage *msg, void *userdata);
5753a5a1b3Sopenharmony_cistatic void handle_get_default_channels(DBusConnection *conn, DBusMessage *msg, void *userdata);
5853a5a1b3Sopenharmony_cistatic void handle_set_default_channels(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
5953a5a1b3Sopenharmony_cistatic void handle_get_default_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata);
6053a5a1b3Sopenharmony_cistatic void handle_set_default_sample_format(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
6153a5a1b3Sopenharmony_cistatic void handle_get_default_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
6253a5a1b3Sopenharmony_cistatic void handle_set_default_sample_rate(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
6353a5a1b3Sopenharmony_cistatic void handle_get_alternate_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
6453a5a1b3Sopenharmony_cistatic void handle_set_alternate_sample_rate(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
6553a5a1b3Sopenharmony_cistatic void handle_get_cards(DBusConnection *conn, DBusMessage *msg, void *userdata);
6653a5a1b3Sopenharmony_cistatic void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata);
6753a5a1b3Sopenharmony_cistatic void handle_get_fallback_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
6853a5a1b3Sopenharmony_cistatic void handle_set_fallback_sink(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
6953a5a1b3Sopenharmony_cistatic void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata);
7053a5a1b3Sopenharmony_cistatic void handle_get_fallback_source(DBusConnection *conn, DBusMessage *msg, void *userdata);
7153a5a1b3Sopenharmony_cistatic void handle_set_fallback_source(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
7253a5a1b3Sopenharmony_cistatic void handle_get_playback_streams(DBusConnection *conn, DBusMessage *msg, void *userdata);
7353a5a1b3Sopenharmony_cistatic void handle_get_record_streams(DBusConnection *conn, DBusMessage *msg, void *userdata);
7453a5a1b3Sopenharmony_cistatic void handle_get_samples(DBusConnection *conn, DBusMessage *msg, void *userdata);
7553a5a1b3Sopenharmony_cistatic void handle_get_modules(DBusConnection *conn, DBusMessage *msg, void *userdata);
7653a5a1b3Sopenharmony_cistatic void handle_get_clients(DBusConnection *conn, DBusMessage *msg, void *userdata);
7753a5a1b3Sopenharmony_cistatic void handle_get_my_client(DBusConnection *conn, DBusMessage *msg, void *userdata);
7853a5a1b3Sopenharmony_cistatic void handle_get_extensions(DBusConnection *conn, DBusMessage *msg, void *userdata);
7953a5a1b3Sopenharmony_ci
8053a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
8153a5a1b3Sopenharmony_ci
8253a5a1b3Sopenharmony_cistatic void handle_get_card_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
8353a5a1b3Sopenharmony_cistatic void handle_get_sink_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
8453a5a1b3Sopenharmony_cistatic void handle_get_source_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
8553a5a1b3Sopenharmony_cistatic void handle_get_sample_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
8653a5a1b3Sopenharmony_cistatic void handle_upload_sample(DBusConnection *conn, DBusMessage *msg, void *userdata);
8753a5a1b3Sopenharmony_cistatic void handle_load_module(DBusConnection *conn, DBusMessage *msg, void *userdata);
8853a5a1b3Sopenharmony_cistatic void handle_exit(DBusConnection *conn, DBusMessage *msg, void *userdata);
8953a5a1b3Sopenharmony_cistatic void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata);
9053a5a1b3Sopenharmony_cistatic void handle_stop_listening_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata);
9153a5a1b3Sopenharmony_ci
9253a5a1b3Sopenharmony_cistruct pa_dbusiface_core {
9353a5a1b3Sopenharmony_ci    pa_core *core;
9453a5a1b3Sopenharmony_ci
9553a5a1b3Sopenharmony_ci    pa_dbus_protocol *dbus_protocol;
9653a5a1b3Sopenharmony_ci
9753a5a1b3Sopenharmony_ci    pa_hashmap *cards;
9853a5a1b3Sopenharmony_ci    pa_hashmap *sinks_by_index;
9953a5a1b3Sopenharmony_ci    pa_hashmap *sinks_by_path;
10053a5a1b3Sopenharmony_ci    pa_hashmap *sources_by_index;
10153a5a1b3Sopenharmony_ci    pa_hashmap *sources_by_path;
10253a5a1b3Sopenharmony_ci    pa_hashmap *playback_streams;
10353a5a1b3Sopenharmony_ci    pa_hashmap *record_streams;
10453a5a1b3Sopenharmony_ci    pa_hashmap *samples;
10553a5a1b3Sopenharmony_ci    pa_hashmap *modules;
10653a5a1b3Sopenharmony_ci    pa_hashmap *clients;
10753a5a1b3Sopenharmony_ci
10853a5a1b3Sopenharmony_ci    pa_sink *fallback_sink;
10953a5a1b3Sopenharmony_ci    pa_source *fallback_source;
11053a5a1b3Sopenharmony_ci
11153a5a1b3Sopenharmony_ci    pa_hook_slot *module_new_slot;
11253a5a1b3Sopenharmony_ci    pa_hook_slot *module_removed_slot;
11353a5a1b3Sopenharmony_ci    pa_hook_slot *default_sink_changed_slot;
11453a5a1b3Sopenharmony_ci    pa_hook_slot *default_source_changed_slot;
11553a5a1b3Sopenharmony_ci    pa_hook_slot *sample_cache_new_slot;
11653a5a1b3Sopenharmony_ci    pa_hook_slot *sample_cache_removed_slot;
11753a5a1b3Sopenharmony_ci    pa_hook_slot *card_put_slot;
11853a5a1b3Sopenharmony_ci    pa_hook_slot *card_unlink_slot;
11953a5a1b3Sopenharmony_ci    pa_hook_slot *sink_input_put_slot;
12053a5a1b3Sopenharmony_ci    pa_hook_slot *sink_input_unlink_slot;
12153a5a1b3Sopenharmony_ci    pa_hook_slot *source_output_put_slot;
12253a5a1b3Sopenharmony_ci    pa_hook_slot *source_output_unlink_slot;
12353a5a1b3Sopenharmony_ci    pa_hook_slot *client_put_slot;
12453a5a1b3Sopenharmony_ci    pa_hook_slot *client_unlink_slot;
12553a5a1b3Sopenharmony_ci    pa_hook_slot *sink_put_slot;
12653a5a1b3Sopenharmony_ci    pa_hook_slot *sink_unlink_slot;
12753a5a1b3Sopenharmony_ci    pa_hook_slot *source_put_slot;
12853a5a1b3Sopenharmony_ci    pa_hook_slot *source_unlink_slot;
12953a5a1b3Sopenharmony_ci    pa_hook_slot *extension_registered_slot;
13053a5a1b3Sopenharmony_ci    pa_hook_slot *extension_unregistered_slot;
13153a5a1b3Sopenharmony_ci
13253a5a1b3Sopenharmony_ci    pa_dbusiface_memstats *memstats;
13353a5a1b3Sopenharmony_ci};
13453a5a1b3Sopenharmony_ci
13553a5a1b3Sopenharmony_cienum property_handler_index {
13653a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_INTERFACE_REVISION,
13753a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_NAME,
13853a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_VERSION,
13953a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_IS_LOCAL,
14053a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_USERNAME,
14153a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_HOSTNAME,
14253a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_DEFAULT_CHANNELS,
14353a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_DEFAULT_SAMPLE_FORMAT,
14453a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_DEFAULT_SAMPLE_RATE,
14553a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_ALTERNATE_SAMPLE_RATE,
14653a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_CARDS,
14753a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_SINKS,
14853a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_FALLBACK_SINK,
14953a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_SOURCES,
15053a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_FALLBACK_SOURCE,
15153a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_PLAYBACK_STREAMS,
15253a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_RECORD_STREAMS,
15353a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_SAMPLES,
15453a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_MODULES,
15553a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_CLIENTS,
15653a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_MY_CLIENT,
15753a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_EXTENSIONS,
15853a5a1b3Sopenharmony_ci    PROPERTY_HANDLER_MAX
15953a5a1b3Sopenharmony_ci};
16053a5a1b3Sopenharmony_ci
16153a5a1b3Sopenharmony_cistatic pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
16253a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_INTERFACE_REVISION]    = { .property_name = "InterfaceRevision",   .type = "u",  .get_cb = handle_get_interface_revision,    .set_cb = NULL },
16353a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_NAME]                  = { .property_name = "Name",                .type = "s",  .get_cb = handle_get_name,                  .set_cb = NULL },
16453a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_VERSION]               = { .property_name = "Version",             .type = "s",  .get_cb = handle_get_version,               .set_cb = NULL },
16553a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_IS_LOCAL]              = { .property_name = "IsLocal",             .type = "b",  .get_cb = handle_get_is_local,              .set_cb = NULL },
16653a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_USERNAME]              = { .property_name = "Username",            .type = "s",  .get_cb = handle_get_username,              .set_cb = NULL },
16753a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_HOSTNAME]              = { .property_name = "Hostname",            .type = "s",  .get_cb = handle_get_hostname,              .set_cb = NULL },
16853a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_DEFAULT_CHANNELS]      = { .property_name = "DefaultChannels",     .type = "au", .get_cb = handle_get_default_channels,      .set_cb = handle_set_default_channels },
16953a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_DEFAULT_SAMPLE_FORMAT] = { .property_name = "DefaultSampleFormat", .type = "u",  .get_cb = handle_get_default_sample_format, .set_cb = handle_set_default_sample_format },
17053a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_DEFAULT_SAMPLE_RATE]   = { .property_name = "DefaultSampleRate",   .type = "u",  .get_cb = handle_get_default_sample_rate,   .set_cb = handle_set_default_sample_rate },
17153a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_ALTERNATE_SAMPLE_RATE]   = { .property_name = "AlternateSampleRate",   .type = "u",  .get_cb = handle_get_alternate_sample_rate,   .set_cb = handle_set_alternate_sample_rate },
17253a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_CARDS]                 = { .property_name = "Cards",               .type = "ao", .get_cb = handle_get_cards,                 .set_cb = NULL },
17353a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_SINKS]                 = { .property_name = "Sinks",               .type = "ao", .get_cb = handle_get_sinks,                 .set_cb = NULL },
17453a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_FALLBACK_SINK]         = { .property_name = "FallbackSink",        .type = "o",  .get_cb = handle_get_fallback_sink,         .set_cb = handle_set_fallback_sink },
17553a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_SOURCES]               = { .property_name = "Sources",             .type = "ao", .get_cb = handle_get_sources,               .set_cb = NULL },
17653a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_FALLBACK_SOURCE]       = { .property_name = "FallbackSource",      .type = "o",  .get_cb = handle_get_fallback_source,       .set_cb = handle_set_fallback_source },
17753a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_PLAYBACK_STREAMS]      = { .property_name = "PlaybackStreams",     .type = "ao", .get_cb = handle_get_playback_streams,      .set_cb = NULL },
17853a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_RECORD_STREAMS]        = { .property_name = "RecordStreams",       .type = "ao", .get_cb = handle_get_record_streams,        .set_cb = NULL },
17953a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_SAMPLES]               = { .property_name = "Samples",             .type = "ao", .get_cb = handle_get_samples,               .set_cb = NULL },
18053a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_MODULES]               = { .property_name = "Modules",             .type = "ao", .get_cb = handle_get_modules,               .set_cb = NULL },
18153a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_CLIENTS]               = { .property_name = "Clients",             .type = "ao", .get_cb = handle_get_clients,               .set_cb = NULL },
18253a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_MY_CLIENT]             = { .property_name = "MyClient",            .type = "o",  .get_cb = handle_get_my_client,             .set_cb = NULL },
18353a5a1b3Sopenharmony_ci    [PROPERTY_HANDLER_EXTENSIONS]            = { .property_name = "Extensions",          .type = "as", .get_cb = handle_get_extensions,            .set_cb = NULL }
18453a5a1b3Sopenharmony_ci};
18553a5a1b3Sopenharmony_ci
18653a5a1b3Sopenharmony_cienum method_handler_index {
18753a5a1b3Sopenharmony_ci    METHOD_HANDLER_GET_CARD_BY_NAME,
18853a5a1b3Sopenharmony_ci    METHOD_HANDLER_GET_SINK_BY_NAME,
18953a5a1b3Sopenharmony_ci    METHOD_HANDLER_GET_SOURCE_BY_NAME,
19053a5a1b3Sopenharmony_ci    METHOD_HANDLER_GET_SAMPLE_BY_NAME,
19153a5a1b3Sopenharmony_ci    METHOD_HANDLER_UPLOAD_SAMPLE,
19253a5a1b3Sopenharmony_ci    METHOD_HANDLER_LOAD_MODULE,
19353a5a1b3Sopenharmony_ci    METHOD_HANDLER_EXIT,
19453a5a1b3Sopenharmony_ci    METHOD_HANDLER_LISTEN_FOR_SIGNAL,
19553a5a1b3Sopenharmony_ci    METHOD_HANDLER_STOP_LISTENING_FOR_SIGNAL,
19653a5a1b3Sopenharmony_ci    METHOD_HANDLER_MAX
19753a5a1b3Sopenharmony_ci};
19853a5a1b3Sopenharmony_ci
19953a5a1b3Sopenharmony_cistatic pa_dbus_arg_info get_card_by_name_args[] = { { "name", "s", "in" }, { "card", "o", "out" } };
20053a5a1b3Sopenharmony_cistatic pa_dbus_arg_info get_sink_by_name_args[] = { { "name", "s", "in" }, { "sink", "o", "out" } };
20153a5a1b3Sopenharmony_cistatic pa_dbus_arg_info get_source_by_name_args[] = { { "name", "s", "in" }, { "source", "o", "out" } };
20253a5a1b3Sopenharmony_cistatic pa_dbus_arg_info get_sample_by_name_args[] = { { "name", "s", "in" }, { "sample", "o", "out" } };
20353a5a1b3Sopenharmony_cistatic pa_dbus_arg_info upload_sample_args[] = { { "name",           "s",      "in" },
20453a5a1b3Sopenharmony_ci                                                 { "sample_format",  "u",      "in" },
20553a5a1b3Sopenharmony_ci                                                 { "sample_rate",    "u",      "in" },
20653a5a1b3Sopenharmony_ci                                                 { "channels",       "au",     "in" },
20753a5a1b3Sopenharmony_ci                                                 { "default_volume", "au",     "in" },
20853a5a1b3Sopenharmony_ci                                                 { "property_list",  "a{say}", "in" },
20953a5a1b3Sopenharmony_ci                                                 { "data",           "ay",     "in" },
21053a5a1b3Sopenharmony_ci                                                 { "sample",         "o",      "out" } };
21153a5a1b3Sopenharmony_cistatic pa_dbus_arg_info load_module_args[] = { { "name", "s", "in" }, { "arguments", "a{ss}", "in" }, { "module", "o", "out" } };
21253a5a1b3Sopenharmony_cistatic pa_dbus_arg_info listen_for_signal_args[] = { { "signal", "s", "in" }, { "objects", "ao", "in" } };
21353a5a1b3Sopenharmony_cistatic pa_dbus_arg_info stop_listening_for_signal_args[] = { { "signal", "s", "in" } };
21453a5a1b3Sopenharmony_ci
21553a5a1b3Sopenharmony_cistatic pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
21653a5a1b3Sopenharmony_ci    [METHOD_HANDLER_GET_CARD_BY_NAME] = {
21753a5a1b3Sopenharmony_ci        .method_name = "GetCardByName",
21853a5a1b3Sopenharmony_ci        .arguments = get_card_by_name_args,
21953a5a1b3Sopenharmony_ci        .n_arguments = sizeof(get_card_by_name_args) / sizeof(pa_dbus_arg_info),
22053a5a1b3Sopenharmony_ci        .receive_cb = handle_get_card_by_name },
22153a5a1b3Sopenharmony_ci    [METHOD_HANDLER_GET_SINK_BY_NAME] = {
22253a5a1b3Sopenharmony_ci        .method_name = "GetSinkByName",
22353a5a1b3Sopenharmony_ci        .arguments = get_sink_by_name_args,
22453a5a1b3Sopenharmony_ci        .n_arguments = sizeof(get_sink_by_name_args) / sizeof(pa_dbus_arg_info),
22553a5a1b3Sopenharmony_ci        .receive_cb = handle_get_sink_by_name },
22653a5a1b3Sopenharmony_ci    [METHOD_HANDLER_GET_SOURCE_BY_NAME] = {
22753a5a1b3Sopenharmony_ci        .method_name = "GetSourceByName",
22853a5a1b3Sopenharmony_ci        .arguments = get_source_by_name_args,
22953a5a1b3Sopenharmony_ci        .n_arguments = sizeof(get_source_by_name_args) / sizeof(pa_dbus_arg_info),
23053a5a1b3Sopenharmony_ci        .receive_cb = handle_get_source_by_name },
23153a5a1b3Sopenharmony_ci    [METHOD_HANDLER_GET_SAMPLE_BY_NAME] = {
23253a5a1b3Sopenharmony_ci        .method_name = "GetSampleByName",
23353a5a1b3Sopenharmony_ci        .arguments = get_sample_by_name_args,
23453a5a1b3Sopenharmony_ci        .n_arguments = sizeof(get_sample_by_name_args) / sizeof(pa_dbus_arg_info),
23553a5a1b3Sopenharmony_ci        .receive_cb = handle_get_sample_by_name },
23653a5a1b3Sopenharmony_ci    [METHOD_HANDLER_UPLOAD_SAMPLE] = {
23753a5a1b3Sopenharmony_ci        .method_name = "UploadSample",
23853a5a1b3Sopenharmony_ci        .arguments = upload_sample_args,
23953a5a1b3Sopenharmony_ci        .n_arguments = sizeof(upload_sample_args) / sizeof(pa_dbus_arg_info),
24053a5a1b3Sopenharmony_ci        .receive_cb = handle_upload_sample },
24153a5a1b3Sopenharmony_ci    [METHOD_HANDLER_LOAD_MODULE] = {
24253a5a1b3Sopenharmony_ci        .method_name = "LoadModule",
24353a5a1b3Sopenharmony_ci        .arguments = load_module_args,
24453a5a1b3Sopenharmony_ci        .n_arguments = sizeof(load_module_args) / sizeof(pa_dbus_arg_info),
24553a5a1b3Sopenharmony_ci        .receive_cb = handle_load_module },
24653a5a1b3Sopenharmony_ci    [METHOD_HANDLER_EXIT] = {
24753a5a1b3Sopenharmony_ci        .method_name = "Exit",
24853a5a1b3Sopenharmony_ci        .arguments = NULL,
24953a5a1b3Sopenharmony_ci        .n_arguments = 0,
25053a5a1b3Sopenharmony_ci        .receive_cb = handle_exit },
25153a5a1b3Sopenharmony_ci    [METHOD_HANDLER_LISTEN_FOR_SIGNAL] = {
25253a5a1b3Sopenharmony_ci        .method_name = "ListenForSignal",
25353a5a1b3Sopenharmony_ci        .arguments = listen_for_signal_args,
25453a5a1b3Sopenharmony_ci        .n_arguments = sizeof(listen_for_signal_args) / sizeof(pa_dbus_arg_info),
25553a5a1b3Sopenharmony_ci        .receive_cb = handle_listen_for_signal },
25653a5a1b3Sopenharmony_ci    [METHOD_HANDLER_STOP_LISTENING_FOR_SIGNAL] = {
25753a5a1b3Sopenharmony_ci        .method_name = "StopListeningForSignal",
25853a5a1b3Sopenharmony_ci        .arguments = stop_listening_for_signal_args,
25953a5a1b3Sopenharmony_ci        .n_arguments = sizeof(stop_listening_for_signal_args) / sizeof(pa_dbus_arg_info),
26053a5a1b3Sopenharmony_ci        .receive_cb = handle_stop_listening_for_signal }
26153a5a1b3Sopenharmony_ci};
26253a5a1b3Sopenharmony_ci
26353a5a1b3Sopenharmony_cienum signal_index {
26453a5a1b3Sopenharmony_ci    SIGNAL_NEW_CARD,
26553a5a1b3Sopenharmony_ci    SIGNAL_CARD_REMOVED,
26653a5a1b3Sopenharmony_ci    SIGNAL_NEW_SINK,
26753a5a1b3Sopenharmony_ci    SIGNAL_SINK_REMOVED,
26853a5a1b3Sopenharmony_ci    SIGNAL_FALLBACK_SINK_UPDATED,
26953a5a1b3Sopenharmony_ci    SIGNAL_FALLBACK_SINK_UNSET,
27053a5a1b3Sopenharmony_ci    SIGNAL_NEW_SOURCE,
27153a5a1b3Sopenharmony_ci    SIGNAL_SOURCE_REMOVED,
27253a5a1b3Sopenharmony_ci    SIGNAL_FALLBACK_SOURCE_UPDATED,
27353a5a1b3Sopenharmony_ci    SIGNAL_FALLBACK_SOURCE_UNSET,
27453a5a1b3Sopenharmony_ci    SIGNAL_NEW_PLAYBACK_STREAM,
27553a5a1b3Sopenharmony_ci    SIGNAL_PLAYBACK_STREAM_REMOVED,
27653a5a1b3Sopenharmony_ci    SIGNAL_NEW_RECORD_STREAM,
27753a5a1b3Sopenharmony_ci    SIGNAL_RECORD_STREAM_REMOVED,
27853a5a1b3Sopenharmony_ci    SIGNAL_NEW_SAMPLE,
27953a5a1b3Sopenharmony_ci    SIGNAL_SAMPLE_REMOVED,
28053a5a1b3Sopenharmony_ci    SIGNAL_NEW_MODULE,
28153a5a1b3Sopenharmony_ci    SIGNAL_MODULE_REMOVED,
28253a5a1b3Sopenharmony_ci    SIGNAL_NEW_CLIENT,
28353a5a1b3Sopenharmony_ci    SIGNAL_CLIENT_REMOVED,
28453a5a1b3Sopenharmony_ci    SIGNAL_NEW_EXTENSION,
28553a5a1b3Sopenharmony_ci    SIGNAL_EXTENSION_REMOVED,
28653a5a1b3Sopenharmony_ci    SIGNAL_MAX
28753a5a1b3Sopenharmony_ci};
28853a5a1b3Sopenharmony_ci
28953a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_card_args[] =                { { "card",            "o", NULL } };
29053a5a1b3Sopenharmony_cistatic pa_dbus_arg_info card_removed_args[] =            { { "card",            "o", NULL } };
29153a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_sink_args[] =                { { "sink",            "o", NULL } };
29253a5a1b3Sopenharmony_cistatic pa_dbus_arg_info sink_removed_args[] =            { { "sink",            "o", NULL } };
29353a5a1b3Sopenharmony_cistatic pa_dbus_arg_info fallback_sink_updated_args[] =   { { "sink",            "o", NULL } };
29453a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_source_args[] =              { { "source",          "o", NULL } };
29553a5a1b3Sopenharmony_cistatic pa_dbus_arg_info source_removed_args[] =          { { "source",          "o", NULL } };
29653a5a1b3Sopenharmony_cistatic pa_dbus_arg_info fallback_source_updated_args[] = { { "source",          "o", NULL } };
29753a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_playback_stream_args[] =     { { "playback_stream", "o", NULL } };
29853a5a1b3Sopenharmony_cistatic pa_dbus_arg_info playback_stream_removed_args[] = { { "playback_stream", "o", NULL } };
29953a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_record_stream_args[] =       { { "record_stream",   "o", NULL } };
30053a5a1b3Sopenharmony_cistatic pa_dbus_arg_info record_stream_removed_args[] =   { { "record_stream",   "o", NULL } };
30153a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_sample_args[] =              { { "sample",          "o", NULL } };
30253a5a1b3Sopenharmony_cistatic pa_dbus_arg_info sample_removed_args[] =          { { "sample",          "o", NULL } };
30353a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_module_args[] =              { { "module",          "o", NULL } };
30453a5a1b3Sopenharmony_cistatic pa_dbus_arg_info module_removed_args[] =          { { "module",          "o", NULL } };
30553a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_client_args[] =              { { "client",          "o", NULL } };
30653a5a1b3Sopenharmony_cistatic pa_dbus_arg_info client_removed_args[] =          { { "client",          "o", NULL } };
30753a5a1b3Sopenharmony_cistatic pa_dbus_arg_info new_extension_args[] =           { { "extension",       "s", NULL } };
30853a5a1b3Sopenharmony_cistatic pa_dbus_arg_info extension_removed_args[] =       { { "extension",       "s", NULL } };
30953a5a1b3Sopenharmony_ci
31053a5a1b3Sopenharmony_cistatic pa_dbus_signal_info signals[SIGNAL_MAX] = {
31153a5a1b3Sopenharmony_ci    [SIGNAL_NEW_CARD]                = { .name = "NewCard",               .arguments = new_card_args,                .n_arguments = 1 },
31253a5a1b3Sopenharmony_ci    [SIGNAL_CARD_REMOVED]            = { .name = "CardRemoved",           .arguments = card_removed_args,            .n_arguments = 1 },
31353a5a1b3Sopenharmony_ci    [SIGNAL_NEW_SINK]                = { .name = "NewSink",               .arguments = new_sink_args,                .n_arguments = 1 },
31453a5a1b3Sopenharmony_ci    [SIGNAL_SINK_REMOVED]            = { .name = "SinkRemoved",           .arguments = sink_removed_args,            .n_arguments = 1 },
31553a5a1b3Sopenharmony_ci    [SIGNAL_FALLBACK_SINK_UPDATED]   = { .name = "FallbackSinkUpdated",   .arguments = fallback_sink_updated_args,   .n_arguments = 1 },
31653a5a1b3Sopenharmony_ci    [SIGNAL_FALLBACK_SINK_UNSET]     = { .name = "FallbackSinkUnset",     .arguments = NULL,                         .n_arguments = 0 },
31753a5a1b3Sopenharmony_ci    [SIGNAL_NEW_SOURCE]              = { .name = "NewSource",             .arguments = new_source_args,              .n_arguments = 1 },
31853a5a1b3Sopenharmony_ci    [SIGNAL_SOURCE_REMOVED]          = { .name = "SourceRemoved",         .arguments = source_removed_args,          .n_arguments = 1 },
31953a5a1b3Sopenharmony_ci    [SIGNAL_FALLBACK_SOURCE_UPDATED] = { .name = "FallbackSourceUpdated", .arguments = fallback_source_updated_args, .n_arguments = 1 },
32053a5a1b3Sopenharmony_ci    [SIGNAL_FALLBACK_SOURCE_UNSET]   = { .name = "FallbackSourceUnset",   .arguments = NULL,                         .n_arguments = 0 },
32153a5a1b3Sopenharmony_ci    [SIGNAL_NEW_PLAYBACK_STREAM]     = { .name = "NewPlaybackStream",     .arguments = new_playback_stream_args,     .n_arguments = 1 },
32253a5a1b3Sopenharmony_ci    [SIGNAL_PLAYBACK_STREAM_REMOVED] = { .name = "PlaybackStreamRemoved", .arguments = playback_stream_removed_args, .n_arguments = 1 },
32353a5a1b3Sopenharmony_ci    [SIGNAL_NEW_RECORD_STREAM]       = { .name = "NewRecordStream",       .arguments = new_record_stream_args,       .n_arguments = 1 },
32453a5a1b3Sopenharmony_ci    [SIGNAL_RECORD_STREAM_REMOVED]   = { .name = "RecordStreamRemoved",   .arguments = record_stream_removed_args,   .n_arguments = 1 },
32553a5a1b3Sopenharmony_ci    [SIGNAL_NEW_SAMPLE]              = { .name = "NewSample",             .arguments = new_sample_args,              .n_arguments = 1 },
32653a5a1b3Sopenharmony_ci    [SIGNAL_SAMPLE_REMOVED]          = { .name = "SampleRemoved",         .arguments = sample_removed_args,          .n_arguments = 1 },
32753a5a1b3Sopenharmony_ci    [SIGNAL_NEW_MODULE]              = { .name = "NewModule",             .arguments = new_module_args,              .n_arguments = 1 },
32853a5a1b3Sopenharmony_ci    [SIGNAL_MODULE_REMOVED]          = { .name = "ModuleRemoved",         .arguments = module_removed_args,          .n_arguments = 1 },
32953a5a1b3Sopenharmony_ci    [SIGNAL_NEW_CLIENT]              = { .name = "NewClient",             .arguments = new_client_args,              .n_arguments = 1 },
33053a5a1b3Sopenharmony_ci    [SIGNAL_CLIENT_REMOVED]          = { .name = "ClientRemoved",         .arguments = client_removed_args,          .n_arguments = 1 },
33153a5a1b3Sopenharmony_ci    [SIGNAL_NEW_EXTENSION]           = { .name = "NewExtension",          .arguments = new_extension_args,           .n_arguments = 1 },
33253a5a1b3Sopenharmony_ci    [SIGNAL_EXTENSION_REMOVED]       = { .name = "ExtensionRemoved",      .arguments = extension_removed_args,       .n_arguments = 1 }
33353a5a1b3Sopenharmony_ci};
33453a5a1b3Sopenharmony_ci
33553a5a1b3Sopenharmony_cistatic pa_dbus_interface_info core_interface_info = {
33653a5a1b3Sopenharmony_ci    .name = PA_DBUS_CORE_INTERFACE,
33753a5a1b3Sopenharmony_ci    .method_handlers = method_handlers,
33853a5a1b3Sopenharmony_ci    .n_method_handlers = METHOD_HANDLER_MAX,
33953a5a1b3Sopenharmony_ci    .property_handlers = property_handlers,
34053a5a1b3Sopenharmony_ci    .n_property_handlers = PROPERTY_HANDLER_MAX,
34153a5a1b3Sopenharmony_ci    .get_all_properties_cb = handle_get_all,
34253a5a1b3Sopenharmony_ci    .signals = signals,
34353a5a1b3Sopenharmony_ci    .n_signals = SIGNAL_MAX
34453a5a1b3Sopenharmony_ci};
34553a5a1b3Sopenharmony_ci
34653a5a1b3Sopenharmony_cistatic void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
34753a5a1b3Sopenharmony_ci    dbus_uint32_t interface_revision = INTERFACE_REVISION;
34853a5a1b3Sopenharmony_ci
34953a5a1b3Sopenharmony_ci    pa_assert(conn);
35053a5a1b3Sopenharmony_ci    pa_assert(msg);
35153a5a1b3Sopenharmony_ci
35253a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision);
35353a5a1b3Sopenharmony_ci}
35453a5a1b3Sopenharmony_ci
35553a5a1b3Sopenharmony_cistatic void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
35653a5a1b3Sopenharmony_ci    const char *server_name = PACKAGE_NAME;
35753a5a1b3Sopenharmony_ci
35853a5a1b3Sopenharmony_ci    pa_assert(conn);
35953a5a1b3Sopenharmony_ci    pa_assert(msg);
36053a5a1b3Sopenharmony_ci
36153a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &server_name);
36253a5a1b3Sopenharmony_ci}
36353a5a1b3Sopenharmony_ci
36453a5a1b3Sopenharmony_cistatic void handle_get_version(DBusConnection *conn, DBusMessage *msg, void *userdata) {
36553a5a1b3Sopenharmony_ci    const char *version = PACKAGE_VERSION;
36653a5a1b3Sopenharmony_ci
36753a5a1b3Sopenharmony_ci    pa_assert(conn);
36853a5a1b3Sopenharmony_ci    pa_assert(msg);
36953a5a1b3Sopenharmony_ci
37053a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &version);
37153a5a1b3Sopenharmony_ci}
37253a5a1b3Sopenharmony_ci
37353a5a1b3Sopenharmony_cistatic dbus_bool_t get_is_local(DBusConnection *conn) {
37453a5a1b3Sopenharmony_ci    int conn_fd;
37553a5a1b3Sopenharmony_ci
37653a5a1b3Sopenharmony_ci    pa_assert(conn);
37753a5a1b3Sopenharmony_ci
37853a5a1b3Sopenharmony_ci    if (!dbus_connection_get_socket(conn, &conn_fd))
37953a5a1b3Sopenharmony_ci        return FALSE;
38053a5a1b3Sopenharmony_ci
38153a5a1b3Sopenharmony_ci    return pa_socket_is_local(conn_fd);
38253a5a1b3Sopenharmony_ci}
38353a5a1b3Sopenharmony_ci
38453a5a1b3Sopenharmony_cistatic void handle_get_is_local(DBusConnection *conn, DBusMessage *msg, void *userdata) {
38553a5a1b3Sopenharmony_ci    dbus_bool_t is_local;
38653a5a1b3Sopenharmony_ci
38753a5a1b3Sopenharmony_ci    pa_assert(conn);
38853a5a1b3Sopenharmony_ci    pa_assert(msg);
38953a5a1b3Sopenharmony_ci
39053a5a1b3Sopenharmony_ci    is_local = get_is_local(conn);
39153a5a1b3Sopenharmony_ci
39253a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_local);
39353a5a1b3Sopenharmony_ci}
39453a5a1b3Sopenharmony_ci
39553a5a1b3Sopenharmony_cistatic void handle_get_username(DBusConnection *conn, DBusMessage *msg, void *userdata) {
39653a5a1b3Sopenharmony_ci    char *username = NULL;
39753a5a1b3Sopenharmony_ci
39853a5a1b3Sopenharmony_ci    pa_assert(conn);
39953a5a1b3Sopenharmony_ci    pa_assert(msg);
40053a5a1b3Sopenharmony_ci
40153a5a1b3Sopenharmony_ci    username = pa_get_user_name_malloc();
40253a5a1b3Sopenharmony_ci
40353a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &username);
40453a5a1b3Sopenharmony_ci
40553a5a1b3Sopenharmony_ci    pa_xfree(username);
40653a5a1b3Sopenharmony_ci}
40753a5a1b3Sopenharmony_ci
40853a5a1b3Sopenharmony_cistatic void handle_get_hostname(DBusConnection *conn, DBusMessage *msg, void *userdata) {
40953a5a1b3Sopenharmony_ci    char *hostname = NULL;
41053a5a1b3Sopenharmony_ci
41153a5a1b3Sopenharmony_ci    pa_assert(conn);
41253a5a1b3Sopenharmony_ci    pa_assert(msg);
41353a5a1b3Sopenharmony_ci
41453a5a1b3Sopenharmony_ci    hostname = pa_get_host_name_malloc();
41553a5a1b3Sopenharmony_ci
41653a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &hostname);
41753a5a1b3Sopenharmony_ci
41853a5a1b3Sopenharmony_ci    pa_xfree(hostname);
41953a5a1b3Sopenharmony_ci}
42053a5a1b3Sopenharmony_ci
42153a5a1b3Sopenharmony_ci/* Caller frees the returned array. */
42253a5a1b3Sopenharmony_cistatic dbus_uint32_t *get_default_channels(pa_dbusiface_core *c, unsigned *n) {
42353a5a1b3Sopenharmony_ci    dbus_uint32_t *default_channels = NULL;
42453a5a1b3Sopenharmony_ci    unsigned i;
42553a5a1b3Sopenharmony_ci
42653a5a1b3Sopenharmony_ci    pa_assert(c);
42753a5a1b3Sopenharmony_ci    pa_assert(n);
42853a5a1b3Sopenharmony_ci
42953a5a1b3Sopenharmony_ci    *n = c->core->default_channel_map.channels;
43053a5a1b3Sopenharmony_ci    default_channels = pa_xnew(dbus_uint32_t, *n);
43153a5a1b3Sopenharmony_ci
43253a5a1b3Sopenharmony_ci    for (i = 0; i < *n; ++i)
43353a5a1b3Sopenharmony_ci        default_channels[i] = c->core->default_channel_map.map[i];
43453a5a1b3Sopenharmony_ci
43553a5a1b3Sopenharmony_ci    return default_channels;
43653a5a1b3Sopenharmony_ci}
43753a5a1b3Sopenharmony_ci
43853a5a1b3Sopenharmony_cistatic void handle_get_default_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) {
43953a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
44053a5a1b3Sopenharmony_ci    dbus_uint32_t *default_channels = NULL;
44153a5a1b3Sopenharmony_ci    unsigned n;
44253a5a1b3Sopenharmony_ci
44353a5a1b3Sopenharmony_ci    pa_assert(conn);
44453a5a1b3Sopenharmony_ci    pa_assert(msg);
44553a5a1b3Sopenharmony_ci    pa_assert(c);
44653a5a1b3Sopenharmony_ci
44753a5a1b3Sopenharmony_ci    default_channels = get_default_channels(c, &n);
44853a5a1b3Sopenharmony_ci
44953a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, default_channels, n);
45053a5a1b3Sopenharmony_ci
45153a5a1b3Sopenharmony_ci    pa_xfree(default_channels);
45253a5a1b3Sopenharmony_ci}
45353a5a1b3Sopenharmony_ci
45453a5a1b3Sopenharmony_cistatic void handle_set_default_channels(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
45553a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
45653a5a1b3Sopenharmony_ci    DBusMessageIter array_iter;
45753a5a1b3Sopenharmony_ci    pa_channel_map new_channel_map;
45853a5a1b3Sopenharmony_ci    const dbus_uint32_t *default_channels;
45953a5a1b3Sopenharmony_ci    int n_channels;
46053a5a1b3Sopenharmony_ci    unsigned i;
46153a5a1b3Sopenharmony_ci
46253a5a1b3Sopenharmony_ci    pa_assert(conn);
46353a5a1b3Sopenharmony_ci    pa_assert(msg);
46453a5a1b3Sopenharmony_ci    pa_assert(iter);
46553a5a1b3Sopenharmony_ci    pa_assert(c);
46653a5a1b3Sopenharmony_ci
46753a5a1b3Sopenharmony_ci    pa_channel_map_init(&new_channel_map);
46853a5a1b3Sopenharmony_ci
46953a5a1b3Sopenharmony_ci    dbus_message_iter_recurse(iter, &array_iter);
47053a5a1b3Sopenharmony_ci    dbus_message_iter_get_fixed_array(&array_iter, &default_channels, &n_channels);
47153a5a1b3Sopenharmony_ci
47253a5a1b3Sopenharmony_ci    if (n_channels <= 0) {
47353a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Empty channel array.");
47453a5a1b3Sopenharmony_ci        return;
47553a5a1b3Sopenharmony_ci    }
47653a5a1b3Sopenharmony_ci
47753a5a1b3Sopenharmony_ci    if (n_channels > (int) PA_CHANNELS_MAX) {
47853a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
47953a5a1b3Sopenharmony_ci                           "Too many channels: %i. The maximum number of channels is %u.", n_channels, PA_CHANNELS_MAX);
48053a5a1b3Sopenharmony_ci        return;
48153a5a1b3Sopenharmony_ci    }
48253a5a1b3Sopenharmony_ci
48353a5a1b3Sopenharmony_ci    new_channel_map.channels = n_channels;
48453a5a1b3Sopenharmony_ci
48553a5a1b3Sopenharmony_ci    for (i = 0; i < new_channel_map.channels; ++i) {
48653a5a1b3Sopenharmony_ci        if (default_channels[i] >= PA_CHANNEL_POSITION_MAX) {
48753a5a1b3Sopenharmony_ci            pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u.", default_channels[i]);
48853a5a1b3Sopenharmony_ci            return;
48953a5a1b3Sopenharmony_ci        }
49053a5a1b3Sopenharmony_ci
49153a5a1b3Sopenharmony_ci        new_channel_map.map[i] = default_channels[i];
49253a5a1b3Sopenharmony_ci    }
49353a5a1b3Sopenharmony_ci
49453a5a1b3Sopenharmony_ci    c->core->default_channel_map = new_channel_map;
49553a5a1b3Sopenharmony_ci    c->core->default_sample_spec.channels = n_channels;
49653a5a1b3Sopenharmony_ci
49753a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
49853a5a1b3Sopenharmony_ci}
49953a5a1b3Sopenharmony_ci
50053a5a1b3Sopenharmony_cistatic void handle_get_default_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) {
50153a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
50253a5a1b3Sopenharmony_ci    dbus_uint32_t default_sample_format;
50353a5a1b3Sopenharmony_ci
50453a5a1b3Sopenharmony_ci    pa_assert(conn);
50553a5a1b3Sopenharmony_ci    pa_assert(msg);
50653a5a1b3Sopenharmony_ci    pa_assert(c);
50753a5a1b3Sopenharmony_ci
50853a5a1b3Sopenharmony_ci    default_sample_format = c->core->default_sample_spec.format;
50953a5a1b3Sopenharmony_ci
51053a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &default_sample_format);
51153a5a1b3Sopenharmony_ci}
51253a5a1b3Sopenharmony_ci
51353a5a1b3Sopenharmony_cistatic void handle_set_default_sample_format(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
51453a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
51553a5a1b3Sopenharmony_ci    dbus_uint32_t default_sample_format;
51653a5a1b3Sopenharmony_ci
51753a5a1b3Sopenharmony_ci    pa_assert(conn);
51853a5a1b3Sopenharmony_ci    pa_assert(msg);
51953a5a1b3Sopenharmony_ci    pa_assert(iter);
52053a5a1b3Sopenharmony_ci    pa_assert(c);
52153a5a1b3Sopenharmony_ci
52253a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(iter, &default_sample_format);
52353a5a1b3Sopenharmony_ci
52453a5a1b3Sopenharmony_ci    if (!pa_sample_format_valid(default_sample_format)) {
52553a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample format.");
52653a5a1b3Sopenharmony_ci        return;
52753a5a1b3Sopenharmony_ci    }
52853a5a1b3Sopenharmony_ci
52953a5a1b3Sopenharmony_ci    c->core->default_sample_spec.format = default_sample_format;
53053a5a1b3Sopenharmony_ci
53153a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
53253a5a1b3Sopenharmony_ci}
53353a5a1b3Sopenharmony_ci
53453a5a1b3Sopenharmony_cistatic void handle_get_default_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
53553a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
53653a5a1b3Sopenharmony_ci    dbus_uint32_t default_sample_rate;
53753a5a1b3Sopenharmony_ci
53853a5a1b3Sopenharmony_ci    pa_assert(conn);
53953a5a1b3Sopenharmony_ci    pa_assert(msg);
54053a5a1b3Sopenharmony_ci    pa_assert(c);
54153a5a1b3Sopenharmony_ci
54253a5a1b3Sopenharmony_ci    default_sample_rate = c->core->default_sample_spec.rate;
54353a5a1b3Sopenharmony_ci
54453a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &default_sample_rate);
54553a5a1b3Sopenharmony_ci}
54653a5a1b3Sopenharmony_ci
54753a5a1b3Sopenharmony_cistatic void handle_set_default_sample_rate(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
54853a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
54953a5a1b3Sopenharmony_ci    dbus_uint32_t default_sample_rate;
55053a5a1b3Sopenharmony_ci
55153a5a1b3Sopenharmony_ci    pa_assert(conn);
55253a5a1b3Sopenharmony_ci    pa_assert(msg);
55353a5a1b3Sopenharmony_ci    pa_assert(iter);
55453a5a1b3Sopenharmony_ci    pa_assert(c);
55553a5a1b3Sopenharmony_ci
55653a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(iter, &default_sample_rate);
55753a5a1b3Sopenharmony_ci
55853a5a1b3Sopenharmony_ci    if (!pa_sample_rate_valid(default_sample_rate)) {
55953a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample rate.");
56053a5a1b3Sopenharmony_ci        return;
56153a5a1b3Sopenharmony_ci    }
56253a5a1b3Sopenharmony_ci
56353a5a1b3Sopenharmony_ci    c->core->default_sample_spec.rate = default_sample_rate;
56453a5a1b3Sopenharmony_ci
56553a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
56653a5a1b3Sopenharmony_ci}
56753a5a1b3Sopenharmony_ci
56853a5a1b3Sopenharmony_cistatic void handle_get_alternate_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
56953a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
57053a5a1b3Sopenharmony_ci    dbus_uint32_t alternate_sample_rate;
57153a5a1b3Sopenharmony_ci
57253a5a1b3Sopenharmony_ci    pa_assert(conn);
57353a5a1b3Sopenharmony_ci    pa_assert(msg);
57453a5a1b3Sopenharmony_ci    pa_assert(c);
57553a5a1b3Sopenharmony_ci
57653a5a1b3Sopenharmony_ci    alternate_sample_rate = c->core->alternate_sample_rate;
57753a5a1b3Sopenharmony_ci
57853a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &alternate_sample_rate);
57953a5a1b3Sopenharmony_ci}
58053a5a1b3Sopenharmony_ci
58153a5a1b3Sopenharmony_cistatic void handle_set_alternate_sample_rate(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
58253a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
58353a5a1b3Sopenharmony_ci    dbus_uint32_t alternate_sample_rate;
58453a5a1b3Sopenharmony_ci
58553a5a1b3Sopenharmony_ci    pa_assert(conn);
58653a5a1b3Sopenharmony_ci    pa_assert(msg);
58753a5a1b3Sopenharmony_ci    pa_assert(iter);
58853a5a1b3Sopenharmony_ci    pa_assert(c);
58953a5a1b3Sopenharmony_ci
59053a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(iter, &alternate_sample_rate);
59153a5a1b3Sopenharmony_ci
59253a5a1b3Sopenharmony_ci    if (!pa_sample_rate_valid(alternate_sample_rate)) {
59353a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample rate.");
59453a5a1b3Sopenharmony_ci        return;
59553a5a1b3Sopenharmony_ci    }
59653a5a1b3Sopenharmony_ci
59753a5a1b3Sopenharmony_ci    c->core->alternate_sample_rate = alternate_sample_rate;
59853a5a1b3Sopenharmony_ci
59953a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
60053a5a1b3Sopenharmony_ci}
60153a5a1b3Sopenharmony_ci
60253a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */
60353a5a1b3Sopenharmony_cistatic const char **get_cards(pa_dbusiface_core *c, unsigned *n) {
60453a5a1b3Sopenharmony_ci    const char **cards;
60553a5a1b3Sopenharmony_ci    unsigned i = 0;
60653a5a1b3Sopenharmony_ci    void *state = NULL;
60753a5a1b3Sopenharmony_ci    pa_dbusiface_card *card;
60853a5a1b3Sopenharmony_ci
60953a5a1b3Sopenharmony_ci    pa_assert(c);
61053a5a1b3Sopenharmony_ci    pa_assert(n);
61153a5a1b3Sopenharmony_ci
61253a5a1b3Sopenharmony_ci    *n = pa_hashmap_size(c->cards);
61353a5a1b3Sopenharmony_ci
61453a5a1b3Sopenharmony_ci    if (*n == 0)
61553a5a1b3Sopenharmony_ci        return NULL;
61653a5a1b3Sopenharmony_ci
61753a5a1b3Sopenharmony_ci    cards = pa_xnew(const char *, *n);
61853a5a1b3Sopenharmony_ci
61953a5a1b3Sopenharmony_ci    PA_HASHMAP_FOREACH(card, c->cards, state)
62053a5a1b3Sopenharmony_ci        cards[i++] = pa_dbusiface_card_get_path(card);
62153a5a1b3Sopenharmony_ci
62253a5a1b3Sopenharmony_ci    return cards;
62353a5a1b3Sopenharmony_ci}
62453a5a1b3Sopenharmony_ci
62553a5a1b3Sopenharmony_cistatic void handle_get_cards(DBusConnection *conn, DBusMessage *msg, void *userdata) {
62653a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
62753a5a1b3Sopenharmony_ci    const char **cards;
62853a5a1b3Sopenharmony_ci    unsigned n;
62953a5a1b3Sopenharmony_ci
63053a5a1b3Sopenharmony_ci    pa_assert(conn);
63153a5a1b3Sopenharmony_ci    pa_assert(msg);
63253a5a1b3Sopenharmony_ci    pa_assert(c);
63353a5a1b3Sopenharmony_ci
63453a5a1b3Sopenharmony_ci    cards = get_cards(c, &n);
63553a5a1b3Sopenharmony_ci
63653a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, cards, n);
63753a5a1b3Sopenharmony_ci
63853a5a1b3Sopenharmony_ci    pa_xfree(cards);
63953a5a1b3Sopenharmony_ci}
64053a5a1b3Sopenharmony_ci
64153a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */
64253a5a1b3Sopenharmony_cistatic const char **get_sinks(pa_dbusiface_core *c, unsigned *n) {
64353a5a1b3Sopenharmony_ci    const char **sinks;
64453a5a1b3Sopenharmony_ci    unsigned i = 0;
64553a5a1b3Sopenharmony_ci    void *state = NULL;
64653a5a1b3Sopenharmony_ci    pa_dbusiface_device *sink;
64753a5a1b3Sopenharmony_ci
64853a5a1b3Sopenharmony_ci    pa_assert(c);
64953a5a1b3Sopenharmony_ci    pa_assert(n);
65053a5a1b3Sopenharmony_ci
65153a5a1b3Sopenharmony_ci    *n = pa_hashmap_size(c->sinks_by_index);
65253a5a1b3Sopenharmony_ci
65353a5a1b3Sopenharmony_ci    if (*n == 0)
65453a5a1b3Sopenharmony_ci        return NULL;
65553a5a1b3Sopenharmony_ci
65653a5a1b3Sopenharmony_ci    sinks = pa_xnew(const char *, *n);
65753a5a1b3Sopenharmony_ci
65853a5a1b3Sopenharmony_ci    PA_HASHMAP_FOREACH(sink, c->sinks_by_index, state)
65953a5a1b3Sopenharmony_ci        sinks[i++] = pa_dbusiface_device_get_path(sink);
66053a5a1b3Sopenharmony_ci
66153a5a1b3Sopenharmony_ci    return sinks;
66253a5a1b3Sopenharmony_ci}
66353a5a1b3Sopenharmony_ci
66453a5a1b3Sopenharmony_cistatic void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata) {
66553a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
66653a5a1b3Sopenharmony_ci    const char **sinks;
66753a5a1b3Sopenharmony_ci    unsigned n;
66853a5a1b3Sopenharmony_ci
66953a5a1b3Sopenharmony_ci    pa_assert(conn);
67053a5a1b3Sopenharmony_ci    pa_assert(msg);
67153a5a1b3Sopenharmony_ci    pa_assert(c);
67253a5a1b3Sopenharmony_ci
67353a5a1b3Sopenharmony_ci    sinks = get_sinks(c, &n);
67453a5a1b3Sopenharmony_ci
67553a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, sinks, n);
67653a5a1b3Sopenharmony_ci
67753a5a1b3Sopenharmony_ci    pa_xfree(sinks);
67853a5a1b3Sopenharmony_ci}
67953a5a1b3Sopenharmony_ci
68053a5a1b3Sopenharmony_cistatic void handle_get_fallback_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
68153a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
68253a5a1b3Sopenharmony_ci    pa_dbusiface_device *fallback_sink;
68353a5a1b3Sopenharmony_ci    const char *object_path;
68453a5a1b3Sopenharmony_ci
68553a5a1b3Sopenharmony_ci    pa_assert(conn);
68653a5a1b3Sopenharmony_ci    pa_assert(msg);
68753a5a1b3Sopenharmony_ci    pa_assert(c);
68853a5a1b3Sopenharmony_ci
68953a5a1b3Sopenharmony_ci    if (!c->fallback_sink) {
69053a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
69153a5a1b3Sopenharmony_ci                           "There are no sinks, and therefore no fallback sink either.");
69253a5a1b3Sopenharmony_ci        return;
69353a5a1b3Sopenharmony_ci    }
69453a5a1b3Sopenharmony_ci
69553a5a1b3Sopenharmony_ci    pa_assert_se((fallback_sink = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index))));
69653a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_device_get_path(fallback_sink);
69753a5a1b3Sopenharmony_ci
69853a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
69953a5a1b3Sopenharmony_ci}
70053a5a1b3Sopenharmony_ci
70153a5a1b3Sopenharmony_cistatic void handle_set_fallback_sink(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
70253a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
70353a5a1b3Sopenharmony_ci    pa_dbusiface_device *fallback_sink;
70453a5a1b3Sopenharmony_ci    const char *object_path;
70553a5a1b3Sopenharmony_ci
70653a5a1b3Sopenharmony_ci    pa_assert(conn);
70753a5a1b3Sopenharmony_ci    pa_assert(msg);
70853a5a1b3Sopenharmony_ci    pa_assert(iter);
70953a5a1b3Sopenharmony_ci    pa_assert(c);
71053a5a1b3Sopenharmony_ci
71153a5a1b3Sopenharmony_ci    if (!c->fallback_sink) {
71253a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
71353a5a1b3Sopenharmony_ci                           "There are no sinks, and therefore no fallback sink either.");
71453a5a1b3Sopenharmony_ci        return;
71553a5a1b3Sopenharmony_ci    }
71653a5a1b3Sopenharmony_ci
71753a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(iter, &object_path);
71853a5a1b3Sopenharmony_ci
71953a5a1b3Sopenharmony_ci    if (!(fallback_sink = pa_hashmap_get(c->sinks_by_path, object_path))) {
72053a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", object_path);
72153a5a1b3Sopenharmony_ci        return;
72253a5a1b3Sopenharmony_ci    }
72353a5a1b3Sopenharmony_ci
72453a5a1b3Sopenharmony_ci    pa_core_set_configured_default_sink(c->core, pa_dbusiface_device_get_sink(fallback_sink)->name);
72553a5a1b3Sopenharmony_ci
72653a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
72753a5a1b3Sopenharmony_ci}
72853a5a1b3Sopenharmony_ci
72953a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */
73053a5a1b3Sopenharmony_cistatic const char **get_sources(pa_dbusiface_core *c, unsigned *n) {
73153a5a1b3Sopenharmony_ci    const char **sources;
73253a5a1b3Sopenharmony_ci    unsigned i = 0;
73353a5a1b3Sopenharmony_ci    void *state = NULL;
73453a5a1b3Sopenharmony_ci    pa_dbusiface_device *source;
73553a5a1b3Sopenharmony_ci
73653a5a1b3Sopenharmony_ci    pa_assert(c);
73753a5a1b3Sopenharmony_ci    pa_assert(n);
73853a5a1b3Sopenharmony_ci
73953a5a1b3Sopenharmony_ci    *n = pa_hashmap_size(c->sources_by_index);
74053a5a1b3Sopenharmony_ci
74153a5a1b3Sopenharmony_ci    if (*n == 0)
74253a5a1b3Sopenharmony_ci        return NULL;
74353a5a1b3Sopenharmony_ci
74453a5a1b3Sopenharmony_ci    sources = pa_xnew(const char *, *n);
74553a5a1b3Sopenharmony_ci
74653a5a1b3Sopenharmony_ci    PA_HASHMAP_FOREACH(source, c->sources_by_index, state)
74753a5a1b3Sopenharmony_ci        sources[i++] = pa_dbusiface_device_get_path(source);
74853a5a1b3Sopenharmony_ci
74953a5a1b3Sopenharmony_ci    return sources;
75053a5a1b3Sopenharmony_ci}
75153a5a1b3Sopenharmony_ci
75253a5a1b3Sopenharmony_cistatic void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata) {
75353a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
75453a5a1b3Sopenharmony_ci    const char **sources;
75553a5a1b3Sopenharmony_ci    unsigned n;
75653a5a1b3Sopenharmony_ci
75753a5a1b3Sopenharmony_ci    pa_assert(conn);
75853a5a1b3Sopenharmony_ci    pa_assert(msg);
75953a5a1b3Sopenharmony_ci    pa_assert(c);
76053a5a1b3Sopenharmony_ci
76153a5a1b3Sopenharmony_ci    sources = get_sources(c, &n);
76253a5a1b3Sopenharmony_ci
76353a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, sources, n);
76453a5a1b3Sopenharmony_ci
76553a5a1b3Sopenharmony_ci    pa_xfree(sources);
76653a5a1b3Sopenharmony_ci}
76753a5a1b3Sopenharmony_ci
76853a5a1b3Sopenharmony_cistatic void handle_get_fallback_source(DBusConnection *conn, DBusMessage *msg, void *userdata) {
76953a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
77053a5a1b3Sopenharmony_ci    pa_dbusiface_device *fallback_source;
77153a5a1b3Sopenharmony_ci    const char *object_path;
77253a5a1b3Sopenharmony_ci
77353a5a1b3Sopenharmony_ci    pa_assert(conn);
77453a5a1b3Sopenharmony_ci    pa_assert(msg);
77553a5a1b3Sopenharmony_ci    pa_assert(c);
77653a5a1b3Sopenharmony_ci
77753a5a1b3Sopenharmony_ci    if (!c->fallback_source) {
77853a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
77953a5a1b3Sopenharmony_ci                           "There are no sources, and therefore no fallback source either.");
78053a5a1b3Sopenharmony_ci        return;
78153a5a1b3Sopenharmony_ci    }
78253a5a1b3Sopenharmony_ci
78353a5a1b3Sopenharmony_ci    pa_assert_se((fallback_source = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(c->fallback_source->index))));
78453a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_device_get_path(fallback_source);
78553a5a1b3Sopenharmony_ci
78653a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
78753a5a1b3Sopenharmony_ci}
78853a5a1b3Sopenharmony_ci
78953a5a1b3Sopenharmony_cistatic void handle_set_fallback_source(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
79053a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
79153a5a1b3Sopenharmony_ci    pa_dbusiface_device *fallback_source;
79253a5a1b3Sopenharmony_ci    const char *object_path;
79353a5a1b3Sopenharmony_ci
79453a5a1b3Sopenharmony_ci    pa_assert(conn);
79553a5a1b3Sopenharmony_ci    pa_assert(msg);
79653a5a1b3Sopenharmony_ci    pa_assert(iter);
79753a5a1b3Sopenharmony_ci    pa_assert(c);
79853a5a1b3Sopenharmony_ci
79953a5a1b3Sopenharmony_ci    if (!c->fallback_source) {
80053a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
80153a5a1b3Sopenharmony_ci                           "There are no sources, and therefore no fallback source either.");
80253a5a1b3Sopenharmony_ci        return;
80353a5a1b3Sopenharmony_ci    }
80453a5a1b3Sopenharmony_ci
80553a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(iter, &object_path);
80653a5a1b3Sopenharmony_ci
80753a5a1b3Sopenharmony_ci    if (!(fallback_source = pa_hashmap_get(c->sources_by_path, object_path))) {
80853a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", object_path);
80953a5a1b3Sopenharmony_ci        return;
81053a5a1b3Sopenharmony_ci    }
81153a5a1b3Sopenharmony_ci
81253a5a1b3Sopenharmony_ci    pa_core_set_configured_default_source(c->core, pa_dbusiface_device_get_source(fallback_source)->name);
81353a5a1b3Sopenharmony_ci
81453a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
81553a5a1b3Sopenharmony_ci}
81653a5a1b3Sopenharmony_ci
81753a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */
81853a5a1b3Sopenharmony_cistatic const char **get_playback_streams(pa_dbusiface_core *c, unsigned *n) {
81953a5a1b3Sopenharmony_ci    const char **streams;
82053a5a1b3Sopenharmony_ci    unsigned i = 0;
82153a5a1b3Sopenharmony_ci    void *state = NULL;
82253a5a1b3Sopenharmony_ci    pa_dbusiface_stream *stream;
82353a5a1b3Sopenharmony_ci
82453a5a1b3Sopenharmony_ci    pa_assert(c);
82553a5a1b3Sopenharmony_ci    pa_assert(n);
82653a5a1b3Sopenharmony_ci
82753a5a1b3Sopenharmony_ci    *n = pa_hashmap_size(c->playback_streams);
82853a5a1b3Sopenharmony_ci
82953a5a1b3Sopenharmony_ci    if (*n == 0)
83053a5a1b3Sopenharmony_ci        return NULL;
83153a5a1b3Sopenharmony_ci
83253a5a1b3Sopenharmony_ci    streams = pa_xnew(const char *, *n);
83353a5a1b3Sopenharmony_ci
83453a5a1b3Sopenharmony_ci    PA_HASHMAP_FOREACH(stream, c->playback_streams, state)
83553a5a1b3Sopenharmony_ci        streams[i++] = pa_dbusiface_stream_get_path(stream);
83653a5a1b3Sopenharmony_ci
83753a5a1b3Sopenharmony_ci    return streams;
83853a5a1b3Sopenharmony_ci}
83953a5a1b3Sopenharmony_ci
84053a5a1b3Sopenharmony_cistatic void handle_get_playback_streams(DBusConnection *conn, DBusMessage *msg, void *userdata) {
84153a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
84253a5a1b3Sopenharmony_ci    const char **playback_streams;
84353a5a1b3Sopenharmony_ci    unsigned n;
84453a5a1b3Sopenharmony_ci
84553a5a1b3Sopenharmony_ci    pa_assert(conn);
84653a5a1b3Sopenharmony_ci    pa_assert(msg);
84753a5a1b3Sopenharmony_ci    pa_assert(c);
84853a5a1b3Sopenharmony_ci
84953a5a1b3Sopenharmony_ci    playback_streams = get_playback_streams(c, &n);
85053a5a1b3Sopenharmony_ci
85153a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, playback_streams, n);
85253a5a1b3Sopenharmony_ci
85353a5a1b3Sopenharmony_ci    pa_xfree(playback_streams);
85453a5a1b3Sopenharmony_ci}
85553a5a1b3Sopenharmony_ci
85653a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */
85753a5a1b3Sopenharmony_cistatic const char **get_record_streams(pa_dbusiface_core *c, unsigned *n) {
85853a5a1b3Sopenharmony_ci    const char **streams;
85953a5a1b3Sopenharmony_ci    unsigned i = 0;
86053a5a1b3Sopenharmony_ci    void *state = NULL;
86153a5a1b3Sopenharmony_ci    pa_dbusiface_stream *stream;
86253a5a1b3Sopenharmony_ci
86353a5a1b3Sopenharmony_ci    pa_assert(c);
86453a5a1b3Sopenharmony_ci    pa_assert(n);
86553a5a1b3Sopenharmony_ci
86653a5a1b3Sopenharmony_ci    *n = pa_hashmap_size(c->record_streams);
86753a5a1b3Sopenharmony_ci
86853a5a1b3Sopenharmony_ci    if (*n == 0)
86953a5a1b3Sopenharmony_ci        return NULL;
87053a5a1b3Sopenharmony_ci
87153a5a1b3Sopenharmony_ci    streams = pa_xnew(const char *, *n);
87253a5a1b3Sopenharmony_ci
87353a5a1b3Sopenharmony_ci    PA_HASHMAP_FOREACH(stream, c->record_streams, state)
87453a5a1b3Sopenharmony_ci        streams[i++] = pa_dbusiface_stream_get_path(stream);
87553a5a1b3Sopenharmony_ci
87653a5a1b3Sopenharmony_ci    return streams;
87753a5a1b3Sopenharmony_ci}
87853a5a1b3Sopenharmony_ci
87953a5a1b3Sopenharmony_cistatic void handle_get_record_streams(DBusConnection *conn, DBusMessage *msg, void *userdata) {
88053a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
88153a5a1b3Sopenharmony_ci    const char **record_streams;
88253a5a1b3Sopenharmony_ci    unsigned n;
88353a5a1b3Sopenharmony_ci
88453a5a1b3Sopenharmony_ci    pa_assert(conn);
88553a5a1b3Sopenharmony_ci    pa_assert(msg);
88653a5a1b3Sopenharmony_ci    pa_assert(c);
88753a5a1b3Sopenharmony_ci
88853a5a1b3Sopenharmony_ci    record_streams = get_record_streams(c, &n);
88953a5a1b3Sopenharmony_ci
89053a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, record_streams, n);
89153a5a1b3Sopenharmony_ci
89253a5a1b3Sopenharmony_ci    pa_xfree(record_streams);
89353a5a1b3Sopenharmony_ci}
89453a5a1b3Sopenharmony_ci
89553a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */
89653a5a1b3Sopenharmony_cistatic const char **get_samples(pa_dbusiface_core *c, unsigned *n) {
89753a5a1b3Sopenharmony_ci    const char **samples;
89853a5a1b3Sopenharmony_ci    unsigned i = 0;
89953a5a1b3Sopenharmony_ci    void *state = NULL;
90053a5a1b3Sopenharmony_ci    pa_dbusiface_sample *sample;
90153a5a1b3Sopenharmony_ci
90253a5a1b3Sopenharmony_ci    pa_assert(c);
90353a5a1b3Sopenharmony_ci    pa_assert(n);
90453a5a1b3Sopenharmony_ci
90553a5a1b3Sopenharmony_ci    *n = pa_hashmap_size(c->samples);
90653a5a1b3Sopenharmony_ci
90753a5a1b3Sopenharmony_ci    if (*n == 0)
90853a5a1b3Sopenharmony_ci        return NULL;
90953a5a1b3Sopenharmony_ci
91053a5a1b3Sopenharmony_ci    samples = pa_xnew(const char *, *n);
91153a5a1b3Sopenharmony_ci
91253a5a1b3Sopenharmony_ci    PA_HASHMAP_FOREACH(sample, c->samples, state)
91353a5a1b3Sopenharmony_ci        samples[i++] = pa_dbusiface_sample_get_path(sample);
91453a5a1b3Sopenharmony_ci
91553a5a1b3Sopenharmony_ci    return samples;
91653a5a1b3Sopenharmony_ci}
91753a5a1b3Sopenharmony_ci
91853a5a1b3Sopenharmony_cistatic void handle_get_samples(DBusConnection *conn, DBusMessage *msg, void *userdata) {
91953a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
92053a5a1b3Sopenharmony_ci    const char **samples;
92153a5a1b3Sopenharmony_ci    unsigned n;
92253a5a1b3Sopenharmony_ci
92353a5a1b3Sopenharmony_ci    pa_assert(conn);
92453a5a1b3Sopenharmony_ci    pa_assert(msg);
92553a5a1b3Sopenharmony_ci    pa_assert(c);
92653a5a1b3Sopenharmony_ci
92753a5a1b3Sopenharmony_ci    samples = get_samples(c, &n);
92853a5a1b3Sopenharmony_ci
92953a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, samples, n);
93053a5a1b3Sopenharmony_ci
93153a5a1b3Sopenharmony_ci    pa_xfree(samples);
93253a5a1b3Sopenharmony_ci}
93353a5a1b3Sopenharmony_ci
93453a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */
93553a5a1b3Sopenharmony_cistatic const char **get_modules(pa_dbusiface_core *c, unsigned *n) {
93653a5a1b3Sopenharmony_ci    const char **modules;
93753a5a1b3Sopenharmony_ci    unsigned i = 0;
93853a5a1b3Sopenharmony_ci    void *state = NULL;
93953a5a1b3Sopenharmony_ci    pa_dbusiface_module *module;
94053a5a1b3Sopenharmony_ci
94153a5a1b3Sopenharmony_ci    pa_assert(c);
94253a5a1b3Sopenharmony_ci    pa_assert(n);
94353a5a1b3Sopenharmony_ci
94453a5a1b3Sopenharmony_ci    *n = pa_hashmap_size(c->modules);
94553a5a1b3Sopenharmony_ci
94653a5a1b3Sopenharmony_ci    if (*n == 0)
94753a5a1b3Sopenharmony_ci        return NULL;
94853a5a1b3Sopenharmony_ci
94953a5a1b3Sopenharmony_ci    modules = pa_xnew(const char *, *n);
95053a5a1b3Sopenharmony_ci
95153a5a1b3Sopenharmony_ci    PA_HASHMAP_FOREACH(module, c->modules, state)
95253a5a1b3Sopenharmony_ci        modules[i++] = pa_dbusiface_module_get_path(module);
95353a5a1b3Sopenharmony_ci
95453a5a1b3Sopenharmony_ci    return modules;
95553a5a1b3Sopenharmony_ci}
95653a5a1b3Sopenharmony_ci
95753a5a1b3Sopenharmony_cistatic void handle_get_modules(DBusConnection *conn, DBusMessage *msg, void *userdata) {
95853a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
95953a5a1b3Sopenharmony_ci    const char **modules;
96053a5a1b3Sopenharmony_ci    unsigned n;
96153a5a1b3Sopenharmony_ci
96253a5a1b3Sopenharmony_ci    pa_assert(conn);
96353a5a1b3Sopenharmony_ci    pa_assert(msg);
96453a5a1b3Sopenharmony_ci    pa_assert(c);
96553a5a1b3Sopenharmony_ci
96653a5a1b3Sopenharmony_ci    modules = get_modules(c, &n);
96753a5a1b3Sopenharmony_ci
96853a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, modules, n);
96953a5a1b3Sopenharmony_ci
97053a5a1b3Sopenharmony_ci    pa_xfree(modules);
97153a5a1b3Sopenharmony_ci}
97253a5a1b3Sopenharmony_ci
97353a5a1b3Sopenharmony_ci/* The caller frees the array, but not the strings. */
97453a5a1b3Sopenharmony_cistatic const char **get_clients(pa_dbusiface_core *c, unsigned *n) {
97553a5a1b3Sopenharmony_ci    const char **clients;
97653a5a1b3Sopenharmony_ci    unsigned i = 0;
97753a5a1b3Sopenharmony_ci    void *state = NULL;
97853a5a1b3Sopenharmony_ci    pa_dbusiface_client *client;
97953a5a1b3Sopenharmony_ci
98053a5a1b3Sopenharmony_ci    pa_assert(c);
98153a5a1b3Sopenharmony_ci    pa_assert(n);
98253a5a1b3Sopenharmony_ci
98353a5a1b3Sopenharmony_ci    *n = pa_hashmap_size(c->clients);
98453a5a1b3Sopenharmony_ci
98553a5a1b3Sopenharmony_ci    if (*n == 0)
98653a5a1b3Sopenharmony_ci        return NULL;
98753a5a1b3Sopenharmony_ci
98853a5a1b3Sopenharmony_ci    clients = pa_xnew(const char *, *n);
98953a5a1b3Sopenharmony_ci
99053a5a1b3Sopenharmony_ci    PA_HASHMAP_FOREACH(client, c->clients, state)
99153a5a1b3Sopenharmony_ci        clients[i++] = pa_dbusiface_client_get_path(client);
99253a5a1b3Sopenharmony_ci
99353a5a1b3Sopenharmony_ci    return clients;
99453a5a1b3Sopenharmony_ci}
99553a5a1b3Sopenharmony_ci
99653a5a1b3Sopenharmony_cistatic void handle_get_clients(DBusConnection *conn, DBusMessage *msg, void *userdata) {
99753a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
99853a5a1b3Sopenharmony_ci    const char **clients;
99953a5a1b3Sopenharmony_ci    unsigned n;
100053a5a1b3Sopenharmony_ci
100153a5a1b3Sopenharmony_ci    pa_assert(conn);
100253a5a1b3Sopenharmony_ci    pa_assert(msg);
100353a5a1b3Sopenharmony_ci    pa_assert(c);
100453a5a1b3Sopenharmony_ci
100553a5a1b3Sopenharmony_ci    clients = get_clients(c, &n);
100653a5a1b3Sopenharmony_ci
100753a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, clients, n);
100853a5a1b3Sopenharmony_ci
100953a5a1b3Sopenharmony_ci    pa_xfree(clients);
101053a5a1b3Sopenharmony_ci}
101153a5a1b3Sopenharmony_ci
101253a5a1b3Sopenharmony_cistatic const char *get_my_client(pa_dbusiface_core *c, DBusConnection *conn) {
101353a5a1b3Sopenharmony_ci    pa_client *my_client;
101453a5a1b3Sopenharmony_ci
101553a5a1b3Sopenharmony_ci    pa_assert(c);
101653a5a1b3Sopenharmony_ci    pa_assert(conn);
101753a5a1b3Sopenharmony_ci
101853a5a1b3Sopenharmony_ci    pa_assert_se((my_client = pa_dbus_protocol_get_client(c->dbus_protocol, conn)));
101953a5a1b3Sopenharmony_ci
102053a5a1b3Sopenharmony_ci    return pa_dbusiface_client_get_path(pa_hashmap_get(c->clients, PA_UINT32_TO_PTR(my_client->index)));
102153a5a1b3Sopenharmony_ci}
102253a5a1b3Sopenharmony_ci
102353a5a1b3Sopenharmony_cistatic void handle_get_my_client(DBusConnection *conn, DBusMessage *msg, void *userdata) {
102453a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
102553a5a1b3Sopenharmony_ci    const char *my_client;
102653a5a1b3Sopenharmony_ci
102753a5a1b3Sopenharmony_ci    pa_assert(conn);
102853a5a1b3Sopenharmony_ci    pa_assert(msg);
102953a5a1b3Sopenharmony_ci    pa_assert(c);
103053a5a1b3Sopenharmony_ci
103153a5a1b3Sopenharmony_ci    my_client = get_my_client(c, conn);
103253a5a1b3Sopenharmony_ci
103353a5a1b3Sopenharmony_ci    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &my_client);
103453a5a1b3Sopenharmony_ci}
103553a5a1b3Sopenharmony_ci
103653a5a1b3Sopenharmony_cistatic void handle_get_extensions(DBusConnection *conn, DBusMessage *msg, void *userdata) {
103753a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
103853a5a1b3Sopenharmony_ci    const char **extensions;
103953a5a1b3Sopenharmony_ci    unsigned n;
104053a5a1b3Sopenharmony_ci
104153a5a1b3Sopenharmony_ci    pa_assert(conn);
104253a5a1b3Sopenharmony_ci    pa_assert(msg);
104353a5a1b3Sopenharmony_ci    pa_assert(c);
104453a5a1b3Sopenharmony_ci
104553a5a1b3Sopenharmony_ci    extensions = pa_dbus_protocol_get_extensions(c->dbus_protocol, &n);
104653a5a1b3Sopenharmony_ci
104753a5a1b3Sopenharmony_ci    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_STRING, extensions, n);
104853a5a1b3Sopenharmony_ci
104953a5a1b3Sopenharmony_ci    pa_xfree(extensions);
105053a5a1b3Sopenharmony_ci}
105153a5a1b3Sopenharmony_ci
105253a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
105353a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
105453a5a1b3Sopenharmony_ci    DBusMessage *reply = NULL;
105553a5a1b3Sopenharmony_ci    DBusMessageIter msg_iter;
105653a5a1b3Sopenharmony_ci    DBusMessageIter dict_iter;
105753a5a1b3Sopenharmony_ci    dbus_uint32_t interface_revision;
105853a5a1b3Sopenharmony_ci    const char *server_name;
105953a5a1b3Sopenharmony_ci    const char *version;
106053a5a1b3Sopenharmony_ci    dbus_bool_t is_local;
106153a5a1b3Sopenharmony_ci    char *username;
106253a5a1b3Sopenharmony_ci    char *hostname;
106353a5a1b3Sopenharmony_ci    dbus_uint32_t *default_channels;
106453a5a1b3Sopenharmony_ci    unsigned n_default_channels;
106553a5a1b3Sopenharmony_ci    dbus_uint32_t default_sample_format;
106653a5a1b3Sopenharmony_ci    dbus_uint32_t default_sample_rate;
106753a5a1b3Sopenharmony_ci    dbus_uint32_t alternate_sample_rate;
106853a5a1b3Sopenharmony_ci    const char **cards;
106953a5a1b3Sopenharmony_ci    unsigned n_cards;
107053a5a1b3Sopenharmony_ci    const char **sinks;
107153a5a1b3Sopenharmony_ci    unsigned n_sinks;
107253a5a1b3Sopenharmony_ci    const char *fallback_sink;
107353a5a1b3Sopenharmony_ci    const char **sources;
107453a5a1b3Sopenharmony_ci    unsigned n_sources;
107553a5a1b3Sopenharmony_ci    const char *fallback_source;
107653a5a1b3Sopenharmony_ci    const char **playback_streams;
107753a5a1b3Sopenharmony_ci    unsigned n_playback_streams;
107853a5a1b3Sopenharmony_ci    const char **record_streams;
107953a5a1b3Sopenharmony_ci    unsigned n_record_streams;
108053a5a1b3Sopenharmony_ci    const char **samples;
108153a5a1b3Sopenharmony_ci    unsigned n_samples;
108253a5a1b3Sopenharmony_ci    const char **modules;
108353a5a1b3Sopenharmony_ci    unsigned n_modules;
108453a5a1b3Sopenharmony_ci    const char **clients;
108553a5a1b3Sopenharmony_ci    unsigned n_clients;
108653a5a1b3Sopenharmony_ci    const char *my_client;
108753a5a1b3Sopenharmony_ci    const char **extensions;
108853a5a1b3Sopenharmony_ci    unsigned n_extensions;
108953a5a1b3Sopenharmony_ci
109053a5a1b3Sopenharmony_ci    pa_assert(conn);
109153a5a1b3Sopenharmony_ci    pa_assert(msg);
109253a5a1b3Sopenharmony_ci    pa_assert(c);
109353a5a1b3Sopenharmony_ci
109453a5a1b3Sopenharmony_ci    interface_revision = INTERFACE_REVISION;
109553a5a1b3Sopenharmony_ci    server_name = PACKAGE_NAME;
109653a5a1b3Sopenharmony_ci    version = PACKAGE_VERSION;
109753a5a1b3Sopenharmony_ci    is_local = get_is_local(conn);
109853a5a1b3Sopenharmony_ci    username = pa_get_user_name_malloc();
109953a5a1b3Sopenharmony_ci    hostname = pa_get_host_name_malloc();
110053a5a1b3Sopenharmony_ci    default_channels = get_default_channels(c, &n_default_channels);
110153a5a1b3Sopenharmony_ci    default_sample_format = c->core->default_sample_spec.format;
110253a5a1b3Sopenharmony_ci    default_sample_rate = c->core->default_sample_spec.rate;
110353a5a1b3Sopenharmony_ci    alternate_sample_rate = c->core->alternate_sample_rate;
110453a5a1b3Sopenharmony_ci    cards = get_cards(c, &n_cards);
110553a5a1b3Sopenharmony_ci    sinks = get_sinks(c, &n_sinks);
110653a5a1b3Sopenharmony_ci    fallback_sink = c->fallback_sink
110753a5a1b3Sopenharmony_ci                    ? pa_dbusiface_device_get_path(pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index)))
110853a5a1b3Sopenharmony_ci                    : NULL;
110953a5a1b3Sopenharmony_ci    sources = get_sources(c, &n_sources);
111053a5a1b3Sopenharmony_ci    fallback_source = c->fallback_source
111153a5a1b3Sopenharmony_ci                      ? pa_dbusiface_device_get_path(pa_hashmap_get(c->sources_by_index,
111253a5a1b3Sopenharmony_ci                                                                    PA_UINT32_TO_PTR(c->fallback_source->index)))
111353a5a1b3Sopenharmony_ci                      : NULL;
111453a5a1b3Sopenharmony_ci    playback_streams = get_playback_streams(c, &n_playback_streams);
111553a5a1b3Sopenharmony_ci    record_streams = get_record_streams(c, &n_record_streams);
111653a5a1b3Sopenharmony_ci    samples = get_samples(c, &n_samples);
111753a5a1b3Sopenharmony_ci    modules = get_modules(c, &n_modules);
111853a5a1b3Sopenharmony_ci    clients = get_clients(c, &n_clients);
111953a5a1b3Sopenharmony_ci    my_client = get_my_client(c, conn);
112053a5a1b3Sopenharmony_ci    extensions = pa_dbus_protocol_get_extensions(c->dbus_protocol, &n_extensions);
112153a5a1b3Sopenharmony_ci
112253a5a1b3Sopenharmony_ci    pa_assert_se((reply = dbus_message_new_method_return(msg)));
112353a5a1b3Sopenharmony_ci
112453a5a1b3Sopenharmony_ci    dbus_message_iter_init_append(reply, &msg_iter);
112553a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
112653a5a1b3Sopenharmony_ci
112753a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision);
112853a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &server_name);
112953a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VERSION].property_name, DBUS_TYPE_STRING, &version);
113053a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_LOCAL].property_name, DBUS_TYPE_BOOLEAN, &is_local);
113153a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_USERNAME].property_name, DBUS_TYPE_STRING, &username);
113253a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HOSTNAME].property_name, DBUS_TYPE_STRING, &hostname);
113353a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEFAULT_CHANNELS].property_name, DBUS_TYPE_UINT32, default_channels, n_default_channels);
113453a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEFAULT_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &default_sample_format);
113553a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEFAULT_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &default_sample_rate);
113653a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ALTERNATE_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &alternate_sample_rate);
113753a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CARDS].property_name, DBUS_TYPE_OBJECT_PATH, cards, n_cards);
113853a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, sinks, n_sinks);
113953a5a1b3Sopenharmony_ci
114053a5a1b3Sopenharmony_ci    if (fallback_sink)
114153a5a1b3Sopenharmony_ci        pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_FALLBACK_SINK].property_name, DBUS_TYPE_OBJECT_PATH, &fallback_sink);
114253a5a1b3Sopenharmony_ci
114353a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SOURCES].property_name, DBUS_TYPE_OBJECT_PATH, sources, n_sources);
114453a5a1b3Sopenharmony_ci
114553a5a1b3Sopenharmony_ci    if (fallback_source)
114653a5a1b3Sopenharmony_ci        pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_FALLBACK_SOURCE].property_name, DBUS_TYPE_OBJECT_PATH, &fallback_source);
114753a5a1b3Sopenharmony_ci
114853a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PLAYBACK_STREAMS].property_name, DBUS_TYPE_OBJECT_PATH, playback_streams, n_playback_streams);
114953a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_RECORD_STREAMS].property_name, DBUS_TYPE_OBJECT_PATH, record_streams, n_record_streams);
115053a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLES].property_name, DBUS_TYPE_OBJECT_PATH, samples, n_samples);
115153a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MODULES].property_name, DBUS_TYPE_OBJECT_PATH, modules, n_modules);
115253a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENTS].property_name, DBUS_TYPE_OBJECT_PATH, clients, n_clients);
115353a5a1b3Sopenharmony_ci    pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MY_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &my_client);
115453a5a1b3Sopenharmony_ci    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_EXTENSIONS].property_name, DBUS_TYPE_STRING, extensions, n_extensions);
115553a5a1b3Sopenharmony_ci
115653a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
115753a5a1b3Sopenharmony_ci
115853a5a1b3Sopenharmony_ci    pa_assert_se(dbus_connection_send(conn, reply, NULL));
115953a5a1b3Sopenharmony_ci
116053a5a1b3Sopenharmony_ci    dbus_message_unref(reply);
116153a5a1b3Sopenharmony_ci
116253a5a1b3Sopenharmony_ci    pa_xfree(username);
116353a5a1b3Sopenharmony_ci    pa_xfree(hostname);
116453a5a1b3Sopenharmony_ci    pa_xfree(default_channels);
116553a5a1b3Sopenharmony_ci    pa_xfree(cards);
116653a5a1b3Sopenharmony_ci    pa_xfree(sinks);
116753a5a1b3Sopenharmony_ci    pa_xfree(sources);
116853a5a1b3Sopenharmony_ci    pa_xfree(playback_streams);
116953a5a1b3Sopenharmony_ci    pa_xfree(record_streams);
117053a5a1b3Sopenharmony_ci    pa_xfree(samples);
117153a5a1b3Sopenharmony_ci    pa_xfree(modules);
117253a5a1b3Sopenharmony_ci    pa_xfree(clients);
117353a5a1b3Sopenharmony_ci    pa_xfree(extensions);
117453a5a1b3Sopenharmony_ci}
117553a5a1b3Sopenharmony_ci
117653a5a1b3Sopenharmony_cistatic void handle_get_card_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
117753a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
117853a5a1b3Sopenharmony_ci    char *card_name;
117953a5a1b3Sopenharmony_ci    pa_card *card;
118053a5a1b3Sopenharmony_ci    pa_dbusiface_card *dbus_card;
118153a5a1b3Sopenharmony_ci    const char *object_path;
118253a5a1b3Sopenharmony_ci
118353a5a1b3Sopenharmony_ci    pa_assert(conn);
118453a5a1b3Sopenharmony_ci    pa_assert(msg);
118553a5a1b3Sopenharmony_ci    pa_assert(c);
118653a5a1b3Sopenharmony_ci
118753a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &card_name, DBUS_TYPE_INVALID));
118853a5a1b3Sopenharmony_ci
118953a5a1b3Sopenharmony_ci    if (!(card = pa_namereg_get(c->core, card_name, PA_NAMEREG_CARD))) {
119053a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such card.");
119153a5a1b3Sopenharmony_ci        return;
119253a5a1b3Sopenharmony_ci    }
119353a5a1b3Sopenharmony_ci
119453a5a1b3Sopenharmony_ci    pa_assert_se((dbus_card = pa_hashmap_get(c->cards, PA_UINT32_TO_PTR(card->index))));
119553a5a1b3Sopenharmony_ci
119653a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_card_get_path(dbus_card);
119753a5a1b3Sopenharmony_ci
119853a5a1b3Sopenharmony_ci    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
119953a5a1b3Sopenharmony_ci}
120053a5a1b3Sopenharmony_ci
120153a5a1b3Sopenharmony_cistatic void handle_get_sink_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
120253a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
120353a5a1b3Sopenharmony_ci    char *sink_name;
120453a5a1b3Sopenharmony_ci    pa_sink *sink;
120553a5a1b3Sopenharmony_ci    pa_dbusiface_device *dbus_sink;
120653a5a1b3Sopenharmony_ci    const char *object_path;
120753a5a1b3Sopenharmony_ci
120853a5a1b3Sopenharmony_ci    pa_assert(conn);
120953a5a1b3Sopenharmony_ci    pa_assert(msg);
121053a5a1b3Sopenharmony_ci    pa_assert(c);
121153a5a1b3Sopenharmony_ci
121253a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &sink_name, DBUS_TYPE_INVALID));
121353a5a1b3Sopenharmony_ci
121453a5a1b3Sopenharmony_ci    if (!(sink = pa_namereg_get(c->core, sink_name, PA_NAMEREG_SINK))) {
121553a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", sink_name);
121653a5a1b3Sopenharmony_ci        return;
121753a5a1b3Sopenharmony_ci    }
121853a5a1b3Sopenharmony_ci
121953a5a1b3Sopenharmony_ci    pa_assert_se((dbus_sink = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(sink->index))));
122053a5a1b3Sopenharmony_ci
122153a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_device_get_path(dbus_sink);
122253a5a1b3Sopenharmony_ci
122353a5a1b3Sopenharmony_ci    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
122453a5a1b3Sopenharmony_ci}
122553a5a1b3Sopenharmony_ci
122653a5a1b3Sopenharmony_cistatic void handle_get_source_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
122753a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
122853a5a1b3Sopenharmony_ci    char *source_name;
122953a5a1b3Sopenharmony_ci    pa_source *source;
123053a5a1b3Sopenharmony_ci    pa_dbusiface_device *dbus_source;
123153a5a1b3Sopenharmony_ci    const char *object_path;
123253a5a1b3Sopenharmony_ci
123353a5a1b3Sopenharmony_ci    pa_assert(conn);
123453a5a1b3Sopenharmony_ci    pa_assert(msg);
123553a5a1b3Sopenharmony_ci    pa_assert(c);
123653a5a1b3Sopenharmony_ci
123753a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &source_name, DBUS_TYPE_INVALID));
123853a5a1b3Sopenharmony_ci
123953a5a1b3Sopenharmony_ci    if (!(source = pa_namereg_get(c->core, source_name, PA_NAMEREG_SOURCE))) {
124053a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", source_name);
124153a5a1b3Sopenharmony_ci        return;
124253a5a1b3Sopenharmony_ci    }
124353a5a1b3Sopenharmony_ci
124453a5a1b3Sopenharmony_ci    pa_assert_se((dbus_source = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(source->index))));
124553a5a1b3Sopenharmony_ci
124653a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_device_get_path(dbus_source);
124753a5a1b3Sopenharmony_ci
124853a5a1b3Sopenharmony_ci    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
124953a5a1b3Sopenharmony_ci}
125053a5a1b3Sopenharmony_ci
125153a5a1b3Sopenharmony_cistatic void handle_get_sample_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
125253a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
125353a5a1b3Sopenharmony_ci    char *sample_name;
125453a5a1b3Sopenharmony_ci    pa_scache_entry *sample;
125553a5a1b3Sopenharmony_ci    pa_dbusiface_sample *dbus_sample;
125653a5a1b3Sopenharmony_ci    const char *object_path;
125753a5a1b3Sopenharmony_ci
125853a5a1b3Sopenharmony_ci    pa_assert(conn);
125953a5a1b3Sopenharmony_ci    pa_assert(msg);
126053a5a1b3Sopenharmony_ci    pa_assert(c);
126153a5a1b3Sopenharmony_ci
126253a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &sample_name, DBUS_TYPE_INVALID));
126353a5a1b3Sopenharmony_ci
126453a5a1b3Sopenharmony_ci    if (!(sample = pa_namereg_get(c->core, sample_name, PA_NAMEREG_SAMPLE))) {
126553a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such sample.");
126653a5a1b3Sopenharmony_ci        return;
126753a5a1b3Sopenharmony_ci    }
126853a5a1b3Sopenharmony_ci
126953a5a1b3Sopenharmony_ci    pa_assert_se((dbus_sample = pa_hashmap_get(c->samples, PA_UINT32_TO_PTR(sample->index))));
127053a5a1b3Sopenharmony_ci
127153a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_sample_get_path(dbus_sample);
127253a5a1b3Sopenharmony_ci
127353a5a1b3Sopenharmony_ci    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
127453a5a1b3Sopenharmony_ci}
127553a5a1b3Sopenharmony_ci
127653a5a1b3Sopenharmony_cistatic void handle_upload_sample(DBusConnection *conn, DBusMessage *msg, void *userdata) {
127753a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
127853a5a1b3Sopenharmony_ci    DBusMessageIter msg_iter;
127953a5a1b3Sopenharmony_ci    DBusMessageIter array_iter;
128053a5a1b3Sopenharmony_ci    const char *name;
128153a5a1b3Sopenharmony_ci    dbus_uint32_t sample_format;
128253a5a1b3Sopenharmony_ci    dbus_uint32_t sample_rate;
128353a5a1b3Sopenharmony_ci    const dbus_uint32_t *channels;
128453a5a1b3Sopenharmony_ci    int n_channels;
128553a5a1b3Sopenharmony_ci    const dbus_uint32_t *default_volume;
128653a5a1b3Sopenharmony_ci    int n_volume_entries;
128753a5a1b3Sopenharmony_ci    pa_proplist *property_list;
128853a5a1b3Sopenharmony_ci    const uint8_t *data;
128953a5a1b3Sopenharmony_ci    int data_length;
129053a5a1b3Sopenharmony_ci    int i;
129153a5a1b3Sopenharmony_ci    pa_sample_spec ss;
129253a5a1b3Sopenharmony_ci    pa_channel_map map;
129353a5a1b3Sopenharmony_ci    pa_memchunk chunk;
129453a5a1b3Sopenharmony_ci    uint32_t idx;
129553a5a1b3Sopenharmony_ci    pa_dbusiface_sample *dbus_sample = NULL;
129653a5a1b3Sopenharmony_ci    pa_scache_entry *sample = NULL;
129753a5a1b3Sopenharmony_ci    const char *object_path;
129853a5a1b3Sopenharmony_ci
129953a5a1b3Sopenharmony_ci    pa_assert(conn);
130053a5a1b3Sopenharmony_ci    pa_assert(msg);
130153a5a1b3Sopenharmony_ci    pa_assert(c);
130253a5a1b3Sopenharmony_ci
130353a5a1b3Sopenharmony_ci    chunk.memblock = NULL;
130453a5a1b3Sopenharmony_ci
130553a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_init(msg, &msg_iter));
130653a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(&msg_iter, &name);
130753a5a1b3Sopenharmony_ci
130853a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_next(&msg_iter));
130953a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(&msg_iter, &sample_format);
131053a5a1b3Sopenharmony_ci
131153a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_next(&msg_iter));
131253a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(&msg_iter, &sample_rate);
131353a5a1b3Sopenharmony_ci
131453a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_next(&msg_iter));
131553a5a1b3Sopenharmony_ci    dbus_message_iter_recurse(&msg_iter, &array_iter);
131653a5a1b3Sopenharmony_ci    dbus_message_iter_get_fixed_array(&array_iter, &channels, &n_channels);
131753a5a1b3Sopenharmony_ci
131853a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_next(&msg_iter));
131953a5a1b3Sopenharmony_ci    dbus_message_iter_recurse(&msg_iter, &array_iter);
132053a5a1b3Sopenharmony_ci    dbus_message_iter_get_fixed_array(&array_iter, &default_volume, &n_volume_entries);
132153a5a1b3Sopenharmony_ci
132253a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_next(&msg_iter));
132353a5a1b3Sopenharmony_ci    if (!(property_list = pa_dbus_get_proplist_arg(conn, msg, &msg_iter)))
132453a5a1b3Sopenharmony_ci        return;
132553a5a1b3Sopenharmony_ci
132653a5a1b3Sopenharmony_ci    dbus_message_iter_recurse(&msg_iter, &array_iter);
132753a5a1b3Sopenharmony_ci    dbus_message_iter_get_fixed_array(&array_iter, &data, &data_length);
132853a5a1b3Sopenharmony_ci
132953a5a1b3Sopenharmony_ci    if (!pa_sample_format_valid(sample_format)) {
133053a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample format.");
133153a5a1b3Sopenharmony_ci        goto finish;
133253a5a1b3Sopenharmony_ci    }
133353a5a1b3Sopenharmony_ci
133453a5a1b3Sopenharmony_ci    if (!pa_sample_rate_valid(sample_rate)) {
133553a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample rate.");
133653a5a1b3Sopenharmony_ci        goto finish;
133753a5a1b3Sopenharmony_ci    }
133853a5a1b3Sopenharmony_ci
133953a5a1b3Sopenharmony_ci    if (n_channels <= 0) {
134053a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Empty channel map.");
134153a5a1b3Sopenharmony_ci        goto finish;
134253a5a1b3Sopenharmony_ci    }
134353a5a1b3Sopenharmony_ci
134453a5a1b3Sopenharmony_ci    if (n_channels > (int) PA_CHANNELS_MAX) {
134553a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
134653a5a1b3Sopenharmony_ci                           "Too many channels: %i. The maximum is %u.", n_channels, PA_CHANNELS_MAX);
134753a5a1b3Sopenharmony_ci        goto finish;
134853a5a1b3Sopenharmony_ci    }
134953a5a1b3Sopenharmony_ci
135053a5a1b3Sopenharmony_ci    for (i = 0; i < n_channels; ++i) {
135153a5a1b3Sopenharmony_ci        if (channels[i] >= PA_CHANNEL_POSITION_MAX) {
135253a5a1b3Sopenharmony_ci            pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position.");
135353a5a1b3Sopenharmony_ci            goto finish;
135453a5a1b3Sopenharmony_ci        }
135553a5a1b3Sopenharmony_ci    }
135653a5a1b3Sopenharmony_ci
135753a5a1b3Sopenharmony_ci    if (n_volume_entries != 0 && n_volume_entries != n_channels) {
135853a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
135953a5a1b3Sopenharmony_ci                           "The channels and default_volume arguments have different number of elements (%i and %i, resp).",
136053a5a1b3Sopenharmony_ci                           n_channels, n_volume_entries);
136153a5a1b3Sopenharmony_ci        goto finish;
136253a5a1b3Sopenharmony_ci    }
136353a5a1b3Sopenharmony_ci
136453a5a1b3Sopenharmony_ci    for (i = 0; i < n_volume_entries; ++i) {
136553a5a1b3Sopenharmony_ci        if (!PA_VOLUME_IS_VALID(default_volume[i])) {
136653a5a1b3Sopenharmony_ci            pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u.", default_volume[i]);
136753a5a1b3Sopenharmony_ci            goto finish;
136853a5a1b3Sopenharmony_ci        }
136953a5a1b3Sopenharmony_ci    }
137053a5a1b3Sopenharmony_ci
137153a5a1b3Sopenharmony_ci    if (data_length == 0) {
137253a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Empty data.");
137353a5a1b3Sopenharmony_ci        goto finish;
137453a5a1b3Sopenharmony_ci    }
137553a5a1b3Sopenharmony_ci
137653a5a1b3Sopenharmony_ci    if (data_length > PA_SCACHE_ENTRY_SIZE_MAX) {
137753a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
137853a5a1b3Sopenharmony_ci                           "Too big sample: %i bytes. The maximum sample length is %u bytes.",
137953a5a1b3Sopenharmony_ci                           data_length, PA_SCACHE_ENTRY_SIZE_MAX);
138053a5a1b3Sopenharmony_ci        goto finish;
138153a5a1b3Sopenharmony_ci    }
138253a5a1b3Sopenharmony_ci
138353a5a1b3Sopenharmony_ci    ss.format = sample_format;
138453a5a1b3Sopenharmony_ci    ss.rate = sample_rate;
138553a5a1b3Sopenharmony_ci    ss.channels = n_channels;
138653a5a1b3Sopenharmony_ci
138753a5a1b3Sopenharmony_ci    pa_assert(pa_sample_spec_valid(&ss));
138853a5a1b3Sopenharmony_ci
138953a5a1b3Sopenharmony_ci    if (!pa_frame_aligned(data_length, &ss)) {
139053a5a1b3Sopenharmony_ci        char buf[PA_SAMPLE_SPEC_SNPRINT_MAX];
139153a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
139253a5a1b3Sopenharmony_ci                           "The sample length (%i bytes) doesn't align with the sample format and channels (%s).",
139353a5a1b3Sopenharmony_ci                           data_length, pa_sample_spec_snprint(buf, sizeof(buf), &ss));
139453a5a1b3Sopenharmony_ci        goto finish;
139553a5a1b3Sopenharmony_ci    }
139653a5a1b3Sopenharmony_ci
139753a5a1b3Sopenharmony_ci    map.channels = n_channels;
139853a5a1b3Sopenharmony_ci    for (i = 0; i < n_channels; ++i)
139953a5a1b3Sopenharmony_ci        map.map[i] = channels[i];
140053a5a1b3Sopenharmony_ci
140153a5a1b3Sopenharmony_ci    chunk.memblock = pa_memblock_new(c->core->mempool, data_length);
140253a5a1b3Sopenharmony_ci    chunk.index = 0;
140353a5a1b3Sopenharmony_ci    chunk.length = data_length;
140453a5a1b3Sopenharmony_ci
140553a5a1b3Sopenharmony_ci    memcpy(pa_memblock_acquire(chunk.memblock), data, data_length);
140653a5a1b3Sopenharmony_ci    pa_memblock_release(chunk.memblock);
140753a5a1b3Sopenharmony_ci
140853a5a1b3Sopenharmony_ci    if (pa_scache_add_item(c->core, name, &ss, &map, &chunk, property_list, &idx) < 0) {
140953a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Adding the sample failed.");
141053a5a1b3Sopenharmony_ci        goto finish;
141153a5a1b3Sopenharmony_ci    }
141253a5a1b3Sopenharmony_ci
141353a5a1b3Sopenharmony_ci    pa_assert_se(sample = pa_idxset_get_by_index(c->core->scache, idx));
141453a5a1b3Sopenharmony_ci
141553a5a1b3Sopenharmony_ci    if (n_volume_entries > 0) {
141653a5a1b3Sopenharmony_ci        sample->volume.channels = n_channels;
141753a5a1b3Sopenharmony_ci        for (i = 0; i < n_volume_entries; ++i)
141853a5a1b3Sopenharmony_ci            sample->volume.values[i] = default_volume[i];
141953a5a1b3Sopenharmony_ci        sample->volume_is_set = true;
142053a5a1b3Sopenharmony_ci    } else {
142153a5a1b3Sopenharmony_ci        sample->volume_is_set = false;
142253a5a1b3Sopenharmony_ci    }
142353a5a1b3Sopenharmony_ci
142453a5a1b3Sopenharmony_ci    dbus_sample = pa_dbusiface_sample_new(c, sample);
142553a5a1b3Sopenharmony_ci    pa_hashmap_put(c->samples, PA_UINT32_TO_PTR(idx), dbus_sample);
142653a5a1b3Sopenharmony_ci
142753a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_sample_get_path(dbus_sample);
142853a5a1b3Sopenharmony_ci
142953a5a1b3Sopenharmony_ci    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
143053a5a1b3Sopenharmony_ci
143153a5a1b3Sopenharmony_cifinish:
143253a5a1b3Sopenharmony_ci    if (property_list)
143353a5a1b3Sopenharmony_ci        pa_proplist_free(property_list);
143453a5a1b3Sopenharmony_ci
143553a5a1b3Sopenharmony_ci    if (chunk.memblock)
143653a5a1b3Sopenharmony_ci        pa_memblock_unref(chunk.memblock);
143753a5a1b3Sopenharmony_ci}
143853a5a1b3Sopenharmony_ci
143953a5a1b3Sopenharmony_cistatic bool contains_space(const char *string) {
144053a5a1b3Sopenharmony_ci    const char *p;
144153a5a1b3Sopenharmony_ci
144253a5a1b3Sopenharmony_ci    pa_assert(string);
144353a5a1b3Sopenharmony_ci
144453a5a1b3Sopenharmony_ci    for (p = string; *p; ++p) {
144553a5a1b3Sopenharmony_ci        if (isspace((unsigned char)*p))
144653a5a1b3Sopenharmony_ci            return true;
144753a5a1b3Sopenharmony_ci    }
144853a5a1b3Sopenharmony_ci
144953a5a1b3Sopenharmony_ci    return false;
145053a5a1b3Sopenharmony_ci}
145153a5a1b3Sopenharmony_ci
145253a5a1b3Sopenharmony_cistatic void handle_load_module(DBusConnection *conn, DBusMessage *msg, void *userdata) {
145353a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
145453a5a1b3Sopenharmony_ci    DBusMessageIter msg_iter;
145553a5a1b3Sopenharmony_ci    DBusMessageIter dict_iter;
145653a5a1b3Sopenharmony_ci    DBusMessageIter dict_entry_iter;
145753a5a1b3Sopenharmony_ci    char *name = NULL;
145853a5a1b3Sopenharmony_ci    const char *key = NULL;
145953a5a1b3Sopenharmony_ci    const char *value = NULL;
146053a5a1b3Sopenharmony_ci    char *escaped_value = NULL;
146153a5a1b3Sopenharmony_ci    pa_strbuf *arg_buffer = NULL;
146253a5a1b3Sopenharmony_ci    char *arg_string = NULL;
146353a5a1b3Sopenharmony_ci    pa_module *module = NULL;
146453a5a1b3Sopenharmony_ci    pa_dbusiface_module *dbus_module = NULL;
146553a5a1b3Sopenharmony_ci    const char *object_path = NULL;
146653a5a1b3Sopenharmony_ci
146753a5a1b3Sopenharmony_ci    pa_assert(conn);
146853a5a1b3Sopenharmony_ci    pa_assert(msg);
146953a5a1b3Sopenharmony_ci    pa_assert(c);
147053a5a1b3Sopenharmony_ci
147153a5a1b3Sopenharmony_ci    if (c->core->disallow_module_loading) {
147253a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "The server is configured to disallow module loading.");
147353a5a1b3Sopenharmony_ci        return;
147453a5a1b3Sopenharmony_ci    }
147553a5a1b3Sopenharmony_ci
147653a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_init(msg, &msg_iter));
147753a5a1b3Sopenharmony_ci    dbus_message_iter_get_basic(&msg_iter, &name);
147853a5a1b3Sopenharmony_ci
147953a5a1b3Sopenharmony_ci    arg_buffer = pa_strbuf_new();
148053a5a1b3Sopenharmony_ci
148153a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_iter_next(&msg_iter));
148253a5a1b3Sopenharmony_ci    dbus_message_iter_recurse(&msg_iter, &dict_iter);
148353a5a1b3Sopenharmony_ci
148453a5a1b3Sopenharmony_ci    while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) {
148553a5a1b3Sopenharmony_ci        if (!pa_strbuf_isempty(arg_buffer))
148653a5a1b3Sopenharmony_ci            pa_strbuf_putc(arg_buffer, ' ');
148753a5a1b3Sopenharmony_ci
148853a5a1b3Sopenharmony_ci        dbus_message_iter_recurse(&dict_iter, &dict_entry_iter);
148953a5a1b3Sopenharmony_ci
149053a5a1b3Sopenharmony_ci        dbus_message_iter_get_basic(&dict_entry_iter, &key);
149153a5a1b3Sopenharmony_ci
149253a5a1b3Sopenharmony_ci        if (strlen(key) <= 0 || !pa_ascii_valid(key) || contains_space(key)) {
149353a5a1b3Sopenharmony_ci            pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid module argument name: %s", key);
149453a5a1b3Sopenharmony_ci            goto finish;
149553a5a1b3Sopenharmony_ci        }
149653a5a1b3Sopenharmony_ci
149753a5a1b3Sopenharmony_ci        pa_assert_se(dbus_message_iter_next(&dict_entry_iter));
149853a5a1b3Sopenharmony_ci        dbus_message_iter_get_basic(&dict_entry_iter, &value);
149953a5a1b3Sopenharmony_ci
150053a5a1b3Sopenharmony_ci        escaped_value = pa_escape(value, "\"");
150153a5a1b3Sopenharmony_ci        pa_strbuf_printf(arg_buffer, "%s=\"%s\"", key, escaped_value);
150253a5a1b3Sopenharmony_ci        pa_xfree(escaped_value);
150353a5a1b3Sopenharmony_ci
150453a5a1b3Sopenharmony_ci        dbus_message_iter_next(&dict_iter);
150553a5a1b3Sopenharmony_ci    }
150653a5a1b3Sopenharmony_ci
150753a5a1b3Sopenharmony_ci    arg_string = pa_strbuf_to_string(arg_buffer);
150853a5a1b3Sopenharmony_ci
150953a5a1b3Sopenharmony_ci    if (pa_module_load(&module, c->core, name, arg_string) < 0) {
151053a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Failed to load module.");
151153a5a1b3Sopenharmony_ci        goto finish;
151253a5a1b3Sopenharmony_ci    }
151353a5a1b3Sopenharmony_ci
151453a5a1b3Sopenharmony_ci    /* This is created during module loading in module_new_cb() */
151553a5a1b3Sopenharmony_ci    dbus_module = pa_hashmap_get(c->modules, PA_UINT32_TO_PTR(module->index));
151653a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_module_get_path(dbus_module);
151753a5a1b3Sopenharmony_ci
151853a5a1b3Sopenharmony_ci    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
151953a5a1b3Sopenharmony_ci
152053a5a1b3Sopenharmony_cifinish:
152153a5a1b3Sopenharmony_ci    if (arg_buffer)
152253a5a1b3Sopenharmony_ci        pa_strbuf_free(arg_buffer);
152353a5a1b3Sopenharmony_ci
152453a5a1b3Sopenharmony_ci    pa_xfree(arg_string);
152553a5a1b3Sopenharmony_ci}
152653a5a1b3Sopenharmony_ci
152753a5a1b3Sopenharmony_cistatic void handle_exit(DBusConnection *conn, DBusMessage *msg, void *userdata) {
152853a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
152953a5a1b3Sopenharmony_ci
153053a5a1b3Sopenharmony_ci    pa_assert(conn);
153153a5a1b3Sopenharmony_ci    pa_assert(msg);
153253a5a1b3Sopenharmony_ci    pa_assert(c);
153353a5a1b3Sopenharmony_ci
153453a5a1b3Sopenharmony_ci    if (c->core->disallow_exit) {
153553a5a1b3Sopenharmony_ci        pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "The server is configured to disallow exiting.");
153653a5a1b3Sopenharmony_ci        return;
153753a5a1b3Sopenharmony_ci    }
153853a5a1b3Sopenharmony_ci
153953a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
154053a5a1b3Sopenharmony_ci
154153a5a1b3Sopenharmony_ci    pa_core_exit(c->core, false, 0);
154253a5a1b3Sopenharmony_ci}
154353a5a1b3Sopenharmony_ci
154453a5a1b3Sopenharmony_cistatic void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata) {
154553a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
154653a5a1b3Sopenharmony_ci    const char *signal_str;
154753a5a1b3Sopenharmony_ci    char **objects = NULL;
154853a5a1b3Sopenharmony_ci    int n_objects;
154953a5a1b3Sopenharmony_ci
155053a5a1b3Sopenharmony_ci    pa_assert(conn);
155153a5a1b3Sopenharmony_ci    pa_assert(msg);
155253a5a1b3Sopenharmony_ci    pa_assert(c);
155353a5a1b3Sopenharmony_ci
155453a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_get_args(msg, NULL,
155553a5a1b3Sopenharmony_ci                                       DBUS_TYPE_STRING, &signal_str,
155653a5a1b3Sopenharmony_ci                                       DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &objects, &n_objects,
155753a5a1b3Sopenharmony_ci                                       DBUS_TYPE_INVALID));
155853a5a1b3Sopenharmony_ci
155953a5a1b3Sopenharmony_ci    pa_dbus_protocol_add_signal_listener(c->dbus_protocol, conn, *signal_str ? signal_str : NULL, objects, n_objects);
156053a5a1b3Sopenharmony_ci
156153a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
156253a5a1b3Sopenharmony_ci
156353a5a1b3Sopenharmony_ci    dbus_free_string_array(objects);
156453a5a1b3Sopenharmony_ci}
156553a5a1b3Sopenharmony_ci
156653a5a1b3Sopenharmony_cistatic void handle_stop_listening_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata) {
156753a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = userdata;
156853a5a1b3Sopenharmony_ci    const char *signal_str;
156953a5a1b3Sopenharmony_ci
157053a5a1b3Sopenharmony_ci    pa_assert(conn);
157153a5a1b3Sopenharmony_ci    pa_assert(msg);
157253a5a1b3Sopenharmony_ci    pa_assert(c);
157353a5a1b3Sopenharmony_ci
157453a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &signal_str, DBUS_TYPE_INVALID));
157553a5a1b3Sopenharmony_ci
157653a5a1b3Sopenharmony_ci    pa_dbus_protocol_remove_signal_listener(c->dbus_protocol, conn, *signal_str ? signal_str : NULL);
157753a5a1b3Sopenharmony_ci
157853a5a1b3Sopenharmony_ci    pa_dbus_send_empty_reply(conn, msg);
157953a5a1b3Sopenharmony_ci}
158053a5a1b3Sopenharmony_ci
158153a5a1b3Sopenharmony_cistatic pa_hook_result_t module_new_cb(void *hook_data, void *call_data, void *slot_data) {
158253a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
158353a5a1b3Sopenharmony_ci    pa_module * module = call_data;
158453a5a1b3Sopenharmony_ci    pa_dbusiface_module *module_iface;
158553a5a1b3Sopenharmony_ci    const char *object_path;
158653a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
158753a5a1b3Sopenharmony_ci
158853a5a1b3Sopenharmony_ci    pa_assert(c);
158953a5a1b3Sopenharmony_ci    pa_assert(module);
159053a5a1b3Sopenharmony_ci
159153a5a1b3Sopenharmony_ci    if (pa_streq(module->name, "module-dbus-protocol")) {
159253a5a1b3Sopenharmony_ci        /* module-dbus-protocol can only be loaded once, and will be accounted
159353a5a1b3Sopenharmony_ci         * for while iterating core->modules in pa_dbusiface_core_new(). As it
159453a5a1b3Sopenharmony_ci         * happens, we will also see it here when the hook is called after the
159553a5a1b3Sopenharmony_ci         * module is initialised, so we ignore it. */
159653a5a1b3Sopenharmony_ci        return PA_HOOK_OK;
159753a5a1b3Sopenharmony_ci    }
159853a5a1b3Sopenharmony_ci
159953a5a1b3Sopenharmony_ci    module_iface = pa_dbusiface_module_new(module);
160053a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->modules, PA_UINT32_TO_PTR(module->index), module_iface) >= 0);
160153a5a1b3Sopenharmony_ci
160253a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_module_get_path(module_iface);
160353a5a1b3Sopenharmony_ci
160453a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
160553a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
160653a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_MODULE].name)));
160753a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
160853a5a1b3Sopenharmony_ci
160953a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
161053a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
161153a5a1b3Sopenharmony_ci
161253a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
161353a5a1b3Sopenharmony_ci}
161453a5a1b3Sopenharmony_ci
161553a5a1b3Sopenharmony_cistatic pa_hook_result_t module_removed_cb(void *hook_data, void *call_data, void *slot_data) {
161653a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
161753a5a1b3Sopenharmony_ci    pa_module * module = call_data;
161853a5a1b3Sopenharmony_ci    pa_dbusiface_module *module_iface;
161953a5a1b3Sopenharmony_ci    const char *object_path;
162053a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
162153a5a1b3Sopenharmony_ci
162253a5a1b3Sopenharmony_ci    pa_assert(c);
162353a5a1b3Sopenharmony_ci    pa_assert(module);
162453a5a1b3Sopenharmony_ci
162553a5a1b3Sopenharmony_ci    pa_assert_se((module_iface = pa_hashmap_remove(c->modules, PA_UINT32_TO_PTR(module->index))));
162653a5a1b3Sopenharmony_ci
162753a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_module_get_path(module_iface);
162853a5a1b3Sopenharmony_ci
162953a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
163053a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
163153a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_MODULE_REMOVED].name)));
163253a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
163353a5a1b3Sopenharmony_ci
163453a5a1b3Sopenharmony_ci    pa_dbusiface_module_free(module_iface);
163553a5a1b3Sopenharmony_ci
163653a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
163753a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
163853a5a1b3Sopenharmony_ci
163953a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
164053a5a1b3Sopenharmony_ci}
164153a5a1b3Sopenharmony_ci
164253a5a1b3Sopenharmony_cistatic pa_hook_result_t sample_cache_new_cb(void *hook_data, void *call_data, void *slot_data) {
164353a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
164453a5a1b3Sopenharmony_ci    pa_scache_entry *sample = call_data;
164553a5a1b3Sopenharmony_ci    pa_dbusiface_sample *sample_iface;
164653a5a1b3Sopenharmony_ci    const char *object_path;
164753a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
164853a5a1b3Sopenharmony_ci
164953a5a1b3Sopenharmony_ci    pa_assert(c);
165053a5a1b3Sopenharmony_ci    pa_assert(sample);
165153a5a1b3Sopenharmony_ci
165253a5a1b3Sopenharmony_ci    sample_iface = pa_dbusiface_sample_new(c, sample);
165353a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->samples, PA_UINT32_TO_PTR(sample->index), sample_iface) >= 0);
165453a5a1b3Sopenharmony_ci
165553a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_sample_get_path(sample_iface);
165653a5a1b3Sopenharmony_ci
165753a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
165853a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
165953a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_SAMPLE].name)));
166053a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
166153a5a1b3Sopenharmony_ci
166253a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
166353a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
166453a5a1b3Sopenharmony_ci
166553a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
166653a5a1b3Sopenharmony_ci}
166753a5a1b3Sopenharmony_ci
166853a5a1b3Sopenharmony_cistatic pa_hook_result_t sample_cache_removed_cb(void *hook_data, void *call_data, void *slot_data) {
166953a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
167053a5a1b3Sopenharmony_ci    pa_scache_entry *sample = call_data;
167153a5a1b3Sopenharmony_ci    pa_dbusiface_sample *sample_iface;
167253a5a1b3Sopenharmony_ci    const char *object_path;
167353a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
167453a5a1b3Sopenharmony_ci
167553a5a1b3Sopenharmony_ci    pa_assert(c);
167653a5a1b3Sopenharmony_ci    pa_assert(sample);
167753a5a1b3Sopenharmony_ci
167853a5a1b3Sopenharmony_ci    pa_assert_se((sample_iface = pa_hashmap_remove(c->samples, PA_UINT32_TO_PTR(sample->index))));
167953a5a1b3Sopenharmony_ci
168053a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_sample_get_path(sample_iface);
168153a5a1b3Sopenharmony_ci
168253a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
168353a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
168453a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_SAMPLE_REMOVED].name)));
168553a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
168653a5a1b3Sopenharmony_ci
168753a5a1b3Sopenharmony_ci    pa_dbusiface_sample_free(sample_iface);
168853a5a1b3Sopenharmony_ci
168953a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
169053a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
169153a5a1b3Sopenharmony_ci
169253a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
169353a5a1b3Sopenharmony_ci}
169453a5a1b3Sopenharmony_ci
169553a5a1b3Sopenharmony_cistatic pa_dbusiface_device *create_dbus_object_for_sink(pa_dbusiface_core *c, pa_sink *s) {
169653a5a1b3Sopenharmony_ci    pa_dbusiface_device *d;
169753a5a1b3Sopenharmony_ci    const char *object_path;
169853a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
169953a5a1b3Sopenharmony_ci
170053a5a1b3Sopenharmony_ci    d = pa_dbusiface_device_new_sink(c, s);
170153a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_device_get_path(d);
170253a5a1b3Sopenharmony_ci
170353a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->sinks_by_index, PA_UINT32_TO_PTR(s->index), d) >= 0);
170453a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->sinks_by_path, (char *) object_path, d) >= 0);
170553a5a1b3Sopenharmony_ci
170653a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
170753a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
170853a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_SINK].name)));
170953a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
171053a5a1b3Sopenharmony_ci
171153a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
171253a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
171353a5a1b3Sopenharmony_ci
171453a5a1b3Sopenharmony_ci    return d;
171553a5a1b3Sopenharmony_ci}
171653a5a1b3Sopenharmony_ci
171753a5a1b3Sopenharmony_cistatic pa_hook_result_t default_sink_changed_cb(void *hook_data, void *call_data, void *slot_data) {
171853a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
171953a5a1b3Sopenharmony_ci    pa_sink *new_fallback_sink = call_data;
172053a5a1b3Sopenharmony_ci    pa_dbusiface_device *device_iface;
172153a5a1b3Sopenharmony_ci    const char *object_path;
172253a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
172353a5a1b3Sopenharmony_ci
172453a5a1b3Sopenharmony_ci    pa_assert(c);
172553a5a1b3Sopenharmony_ci
172653a5a1b3Sopenharmony_ci    if (c->fallback_sink != new_fallback_sink) {
172753a5a1b3Sopenharmony_ci        if (c->fallback_sink)
172853a5a1b3Sopenharmony_ci            pa_sink_unref(c->fallback_sink);
172953a5a1b3Sopenharmony_ci        c->fallback_sink = new_fallback_sink ? pa_sink_ref(new_fallback_sink) : NULL;
173053a5a1b3Sopenharmony_ci
173153a5a1b3Sopenharmony_ci        if (c->fallback_sink) {
173253a5a1b3Sopenharmony_ci            device_iface = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index));
173353a5a1b3Sopenharmony_ci
173453a5a1b3Sopenharmony_ci            /* It's possible that we haven't created a dbus object for the
173553a5a1b3Sopenharmony_ci             * source yet, because if a new source immediately becomes the
173653a5a1b3Sopenharmony_ci             * default source, the default source change hook is fired before
173753a5a1b3Sopenharmony_ci             * the put hook. */
173853a5a1b3Sopenharmony_ci            if (!device_iface)
173953a5a1b3Sopenharmony_ci                device_iface = create_dbus_object_for_sink(c, c->fallback_sink);
174053a5a1b3Sopenharmony_ci
174153a5a1b3Sopenharmony_ci            object_path = pa_dbusiface_device_get_path(device_iface);
174253a5a1b3Sopenharmony_ci
174353a5a1b3Sopenharmony_ci            pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
174453a5a1b3Sopenharmony_ci                                                               PA_DBUS_CORE_INTERFACE,
174553a5a1b3Sopenharmony_ci                                                               signals[SIGNAL_FALLBACK_SINK_UPDATED].name)));
174653a5a1b3Sopenharmony_ci            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
174753a5a1b3Sopenharmony_ci
174853a5a1b3Sopenharmony_ci        } else {
174953a5a1b3Sopenharmony_ci            pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
175053a5a1b3Sopenharmony_ci                                                               PA_DBUS_CORE_INTERFACE,
175153a5a1b3Sopenharmony_ci                                                               signals[SIGNAL_FALLBACK_SINK_UNSET].name)));
175253a5a1b3Sopenharmony_ci        }
175353a5a1b3Sopenharmony_ci    }
175453a5a1b3Sopenharmony_ci
175553a5a1b3Sopenharmony_ci    if (signal_msg) {
175653a5a1b3Sopenharmony_ci        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
175753a5a1b3Sopenharmony_ci        dbus_message_unref(signal_msg);
175853a5a1b3Sopenharmony_ci    }
175953a5a1b3Sopenharmony_ci
176053a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
176153a5a1b3Sopenharmony_ci}
176253a5a1b3Sopenharmony_ci
176353a5a1b3Sopenharmony_cistatic pa_dbusiface_device *create_dbus_object_for_source(pa_dbusiface_core *c, pa_source *s) {
176453a5a1b3Sopenharmony_ci    pa_dbusiface_device *d;
176553a5a1b3Sopenharmony_ci    const char *object_path;
176653a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
176753a5a1b3Sopenharmony_ci
176853a5a1b3Sopenharmony_ci    d = pa_dbusiface_device_new_source(c, s);
176953a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_device_get_path(d);
177053a5a1b3Sopenharmony_ci
177153a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->sources_by_index, PA_UINT32_TO_PTR(s->index), d) >= 0);
177253a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->sources_by_path, (char *) object_path, d) >= 0);
177353a5a1b3Sopenharmony_ci
177453a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
177553a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
177653a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_SOURCE].name)));
177753a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
177853a5a1b3Sopenharmony_ci
177953a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
178053a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
178153a5a1b3Sopenharmony_ci
178253a5a1b3Sopenharmony_ci    return d;
178353a5a1b3Sopenharmony_ci}
178453a5a1b3Sopenharmony_ci
178553a5a1b3Sopenharmony_cistatic pa_hook_result_t default_source_changed_cb(void *hook_data, void *call_data, void *slot_data) {
178653a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
178753a5a1b3Sopenharmony_ci    pa_source *new_fallback_source = call_data;
178853a5a1b3Sopenharmony_ci    pa_dbusiface_device *device_iface;
178953a5a1b3Sopenharmony_ci    const char *object_path;
179053a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
179153a5a1b3Sopenharmony_ci
179253a5a1b3Sopenharmony_ci    pa_assert(c);
179353a5a1b3Sopenharmony_ci
179453a5a1b3Sopenharmony_ci    if (c->fallback_source != new_fallback_source) {
179553a5a1b3Sopenharmony_ci        if (c->fallback_source)
179653a5a1b3Sopenharmony_ci            pa_source_unref(c->fallback_source);
179753a5a1b3Sopenharmony_ci        c->fallback_source = new_fallback_source ? pa_source_ref(new_fallback_source) : NULL;
179853a5a1b3Sopenharmony_ci
179953a5a1b3Sopenharmony_ci        if (c->fallback_source) {
180053a5a1b3Sopenharmony_ci            device_iface = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(c->fallback_source->index));
180153a5a1b3Sopenharmony_ci
180253a5a1b3Sopenharmony_ci            /* It's possible that we haven't created a dbus object for the
180353a5a1b3Sopenharmony_ci             * source yet, because if a new source immediately becomes the
180453a5a1b3Sopenharmony_ci             * default source, the default source change hook is fired before
180553a5a1b3Sopenharmony_ci             * the put hook. */
180653a5a1b3Sopenharmony_ci            if (!device_iface)
180753a5a1b3Sopenharmony_ci                device_iface = create_dbus_object_for_source(c, c->fallback_source);
180853a5a1b3Sopenharmony_ci
180953a5a1b3Sopenharmony_ci            object_path = pa_dbusiface_device_get_path(device_iface);
181053a5a1b3Sopenharmony_ci
181153a5a1b3Sopenharmony_ci            pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
181253a5a1b3Sopenharmony_ci                                                               PA_DBUS_CORE_INTERFACE,
181353a5a1b3Sopenharmony_ci                                                               signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name)));
181453a5a1b3Sopenharmony_ci            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
181553a5a1b3Sopenharmony_ci
181653a5a1b3Sopenharmony_ci        } else {
181753a5a1b3Sopenharmony_ci            pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
181853a5a1b3Sopenharmony_ci                                                               PA_DBUS_CORE_INTERFACE,
181953a5a1b3Sopenharmony_ci                                                               signals[SIGNAL_FALLBACK_SOURCE_UNSET].name)));
182053a5a1b3Sopenharmony_ci        }
182153a5a1b3Sopenharmony_ci    }
182253a5a1b3Sopenharmony_ci
182353a5a1b3Sopenharmony_ci    if (signal_msg) {
182453a5a1b3Sopenharmony_ci        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
182553a5a1b3Sopenharmony_ci        dbus_message_unref(signal_msg);
182653a5a1b3Sopenharmony_ci    }
182753a5a1b3Sopenharmony_ci
182853a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
182953a5a1b3Sopenharmony_ci}
183053a5a1b3Sopenharmony_ci
183153a5a1b3Sopenharmony_cistatic pa_hook_result_t card_put_cb(void *hook_data, void *call_data, void *slot_data) {
183253a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
183353a5a1b3Sopenharmony_ci    pa_card *card = call_data;
183453a5a1b3Sopenharmony_ci    pa_dbusiface_card *card_iface = NULL;
183553a5a1b3Sopenharmony_ci    const char *object_path;
183653a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
183753a5a1b3Sopenharmony_ci
183853a5a1b3Sopenharmony_ci    pa_assert(c);
183953a5a1b3Sopenharmony_ci    pa_assert(card);
184053a5a1b3Sopenharmony_ci
184153a5a1b3Sopenharmony_ci    card_iface = pa_dbusiface_card_new(c, card);
184253a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->cards, PA_UINT32_TO_PTR(card->index), card_iface) >= 0);
184353a5a1b3Sopenharmony_ci
184453a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_card_get_path(card_iface);
184553a5a1b3Sopenharmony_ci
184653a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
184753a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
184853a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_CARD].name)));
184953a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
185053a5a1b3Sopenharmony_ci
185153a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
185253a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
185353a5a1b3Sopenharmony_ci
185453a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
185553a5a1b3Sopenharmony_ci}
185653a5a1b3Sopenharmony_ci
185753a5a1b3Sopenharmony_cistatic pa_hook_result_t card_unlink_cb(void *hook_data, void *call_data, void *slot_data) {
185853a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
185953a5a1b3Sopenharmony_ci    pa_card *card = call_data;
186053a5a1b3Sopenharmony_ci    pa_dbusiface_card *card_iface;
186153a5a1b3Sopenharmony_ci    const char *object_path;
186253a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
186353a5a1b3Sopenharmony_ci
186453a5a1b3Sopenharmony_ci    pa_assert(c);
186553a5a1b3Sopenharmony_ci    pa_assert(card);
186653a5a1b3Sopenharmony_ci
186753a5a1b3Sopenharmony_ci    pa_assert_se((card_iface = pa_hashmap_remove(c->cards, PA_UINT32_TO_PTR(card->index))));
186853a5a1b3Sopenharmony_ci
186953a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_card_get_path(card_iface);
187053a5a1b3Sopenharmony_ci
187153a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
187253a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
187353a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_CARD_REMOVED].name)));
187453a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
187553a5a1b3Sopenharmony_ci
187653a5a1b3Sopenharmony_ci    pa_dbusiface_card_free(card_iface);
187753a5a1b3Sopenharmony_ci
187853a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
187953a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
188053a5a1b3Sopenharmony_ci
188153a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
188253a5a1b3Sopenharmony_ci}
188353a5a1b3Sopenharmony_ci
188453a5a1b3Sopenharmony_cistatic pa_hook_result_t sink_input_put_cb(void *hook_data, void *call_data, void *slot_data) {
188553a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
188653a5a1b3Sopenharmony_ci    pa_sink_input *sink_input = call_data;
188753a5a1b3Sopenharmony_ci    pa_dbusiface_stream *stream_iface;
188853a5a1b3Sopenharmony_ci    const char *object_path;
188953a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
189053a5a1b3Sopenharmony_ci
189153a5a1b3Sopenharmony_ci    pa_assert(c);
189253a5a1b3Sopenharmony_ci    pa_assert(sink_input);
189353a5a1b3Sopenharmony_ci
189453a5a1b3Sopenharmony_ci    stream_iface = pa_dbusiface_stream_new_playback(c, sink_input);
189553a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->playback_streams, PA_UINT32_TO_PTR(sink_input->index), stream_iface) >= 0);
189653a5a1b3Sopenharmony_ci
189753a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_stream_get_path(stream_iface);
189853a5a1b3Sopenharmony_ci
189953a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
190053a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
190153a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_PLAYBACK_STREAM].name)));
190253a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
190353a5a1b3Sopenharmony_ci
190453a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
190553a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
190653a5a1b3Sopenharmony_ci
190753a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
190853a5a1b3Sopenharmony_ci}
190953a5a1b3Sopenharmony_ci
191053a5a1b3Sopenharmony_cistatic pa_hook_result_t sink_input_unlink_cb(void *hook_data, void *call_data, void *slot_data) {
191153a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
191253a5a1b3Sopenharmony_ci    pa_sink_input *sink_input = call_data;
191353a5a1b3Sopenharmony_ci    pa_dbusiface_stream *stream_iface;
191453a5a1b3Sopenharmony_ci    const char *object_path;
191553a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
191653a5a1b3Sopenharmony_ci
191753a5a1b3Sopenharmony_ci    pa_assert(c);
191853a5a1b3Sopenharmony_ci    pa_assert(sink_input);
191953a5a1b3Sopenharmony_ci
192053a5a1b3Sopenharmony_ci    pa_assert_se((stream_iface = pa_hashmap_remove(c->playback_streams, PA_UINT32_TO_PTR(sink_input->index))));
192153a5a1b3Sopenharmony_ci
192253a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_stream_get_path(stream_iface);
192353a5a1b3Sopenharmony_ci
192453a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
192553a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
192653a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_PLAYBACK_STREAM_REMOVED].name)));
192753a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
192853a5a1b3Sopenharmony_ci
192953a5a1b3Sopenharmony_ci    pa_dbusiface_stream_free(stream_iface);
193053a5a1b3Sopenharmony_ci
193153a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
193253a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
193353a5a1b3Sopenharmony_ci
193453a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
193553a5a1b3Sopenharmony_ci}
193653a5a1b3Sopenharmony_ci
193753a5a1b3Sopenharmony_cistatic pa_hook_result_t source_output_put_cb(void *hook_data, void *call_data, void *slot_data) {
193853a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
193953a5a1b3Sopenharmony_ci    pa_source_output *source_output = call_data;
194053a5a1b3Sopenharmony_ci    pa_dbusiface_stream *stream_iface;
194153a5a1b3Sopenharmony_ci    const char *object_path;
194253a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
194353a5a1b3Sopenharmony_ci
194453a5a1b3Sopenharmony_ci    pa_assert(c);
194553a5a1b3Sopenharmony_ci    pa_assert(source_output);
194653a5a1b3Sopenharmony_ci
194753a5a1b3Sopenharmony_ci    stream_iface = pa_dbusiface_stream_new_record(c, source_output);
194853a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->record_streams, PA_UINT32_TO_PTR(source_output->index), stream_iface) >= 0);
194953a5a1b3Sopenharmony_ci
195053a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_stream_get_path(stream_iface);
195153a5a1b3Sopenharmony_ci
195253a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
195353a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
195453a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_RECORD_STREAM].name)));
195553a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
195653a5a1b3Sopenharmony_ci
195753a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
195853a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
195953a5a1b3Sopenharmony_ci
196053a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
196153a5a1b3Sopenharmony_ci}
196253a5a1b3Sopenharmony_ci
196353a5a1b3Sopenharmony_cistatic pa_hook_result_t source_output_unlink_cb(void *hook_data, void *call_data, void *slot_data) {
196453a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
196553a5a1b3Sopenharmony_ci    pa_source_output *source_output = call_data;
196653a5a1b3Sopenharmony_ci    pa_dbusiface_stream *stream_iface;
196753a5a1b3Sopenharmony_ci    const char *object_path;
196853a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
196953a5a1b3Sopenharmony_ci
197053a5a1b3Sopenharmony_ci    pa_assert(c);
197153a5a1b3Sopenharmony_ci    pa_assert(source_output);
197253a5a1b3Sopenharmony_ci
197353a5a1b3Sopenharmony_ci    pa_assert_se((stream_iface = pa_hashmap_remove(c->record_streams, PA_UINT32_TO_PTR(source_output->index))));
197453a5a1b3Sopenharmony_ci
197553a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_stream_get_path(stream_iface);
197653a5a1b3Sopenharmony_ci
197753a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
197853a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
197953a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_RECORD_STREAM_REMOVED].name)));
198053a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
198153a5a1b3Sopenharmony_ci
198253a5a1b3Sopenharmony_ci    pa_dbusiface_stream_free(stream_iface);
198353a5a1b3Sopenharmony_ci
198453a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
198553a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
198653a5a1b3Sopenharmony_ci
198753a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
198853a5a1b3Sopenharmony_ci}
198953a5a1b3Sopenharmony_ci
199053a5a1b3Sopenharmony_cistatic pa_hook_result_t client_put_cb(void *hook_data, void *call_data, void *slot_data) {
199153a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
199253a5a1b3Sopenharmony_ci    pa_client *client = call_data;
199353a5a1b3Sopenharmony_ci    pa_dbusiface_client *client_iface;
199453a5a1b3Sopenharmony_ci    const char *object_path;
199553a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
199653a5a1b3Sopenharmony_ci
199753a5a1b3Sopenharmony_ci    pa_assert(c);
199853a5a1b3Sopenharmony_ci    pa_assert(client);
199953a5a1b3Sopenharmony_ci
200053a5a1b3Sopenharmony_ci    client_iface = pa_dbusiface_client_new(c, client);
200153a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_put(c->clients, PA_UINT32_TO_PTR(client->index), client_iface) >= 0);
200253a5a1b3Sopenharmony_ci
200353a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_client_get_path(client_iface);
200453a5a1b3Sopenharmony_ci
200553a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
200653a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
200753a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_CLIENT].name)));
200853a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
200953a5a1b3Sopenharmony_ci
201053a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
201153a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
201253a5a1b3Sopenharmony_ci
201353a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
201453a5a1b3Sopenharmony_ci}
201553a5a1b3Sopenharmony_ci
201653a5a1b3Sopenharmony_cistatic pa_hook_result_t client_unlink_cb(void *hook_data, void *call_data, void *slot_data) {
201753a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
201853a5a1b3Sopenharmony_ci    pa_client *client = call_data;
201953a5a1b3Sopenharmony_ci    pa_dbusiface_client *client_iface;
202053a5a1b3Sopenharmony_ci    const char *object_path;
202153a5a1b3Sopenharmony_ci    DBusMessage *signal_msg;
202253a5a1b3Sopenharmony_ci
202353a5a1b3Sopenharmony_ci    pa_assert(c);
202453a5a1b3Sopenharmony_ci    pa_assert(client);
202553a5a1b3Sopenharmony_ci
202653a5a1b3Sopenharmony_ci    pa_assert_se((client_iface = pa_hashmap_remove(c->clients, PA_UINT32_TO_PTR(client->index))));
202753a5a1b3Sopenharmony_ci
202853a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_client_get_path(client_iface);
202953a5a1b3Sopenharmony_ci
203053a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
203153a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
203253a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_CLIENT_REMOVED].name)));
203353a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
203453a5a1b3Sopenharmony_ci
203553a5a1b3Sopenharmony_ci    pa_dbusiface_client_free(client_iface);
203653a5a1b3Sopenharmony_ci
203753a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
203853a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
203953a5a1b3Sopenharmony_ci
204053a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
204153a5a1b3Sopenharmony_ci}
204253a5a1b3Sopenharmony_ci
204353a5a1b3Sopenharmony_cistatic pa_hook_result_t sink_put_cb(void *hook_data, void *call_data, void *slot_data) {
204453a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
204553a5a1b3Sopenharmony_ci    pa_sink *s = call_data;
204653a5a1b3Sopenharmony_ci
204753a5a1b3Sopenharmony_ci    pa_assert(c);
204853a5a1b3Sopenharmony_ci    pa_assert(s);
204953a5a1b3Sopenharmony_ci
205053a5a1b3Sopenharmony_ci    /* We may have alredy encountered this sink, because if the new sink was
205153a5a1b3Sopenharmony_ci     * chosen as the default sink, the default sink change hook was fired
205253a5a1b3Sopenharmony_ci     * first, and we saw the sink in default_sink_changed_cb(). */
205353a5a1b3Sopenharmony_ci    if (pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(s->index)))
205453a5a1b3Sopenharmony_ci        return PA_HOOK_OK;
205553a5a1b3Sopenharmony_ci
205653a5a1b3Sopenharmony_ci    create_dbus_object_for_sink(c, s);
205753a5a1b3Sopenharmony_ci
205853a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
205953a5a1b3Sopenharmony_ci}
206053a5a1b3Sopenharmony_ci
206153a5a1b3Sopenharmony_cistatic pa_hook_result_t sink_unlink_cb(void *hook_data, void *call_data, void *slot_data) {
206253a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
206353a5a1b3Sopenharmony_ci    pa_sink *s = call_data;
206453a5a1b3Sopenharmony_ci    pa_dbusiface_device *d = NULL;
206553a5a1b3Sopenharmony_ci    const char *object_path = NULL;
206653a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
206753a5a1b3Sopenharmony_ci
206853a5a1b3Sopenharmony_ci    pa_assert(c);
206953a5a1b3Sopenharmony_ci    pa_assert(s);
207053a5a1b3Sopenharmony_ci
207153a5a1b3Sopenharmony_ci    pa_assert_se(d = pa_hashmap_remove(c->sinks_by_index, PA_UINT32_TO_PTR(s->index)));
207253a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_device_get_path(d);
207353a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_remove(c->sinks_by_path, object_path));
207453a5a1b3Sopenharmony_ci
207553a5a1b3Sopenharmony_ci    pa_assert_se(signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
207653a5a1b3Sopenharmony_ci                                                      PA_DBUS_CORE_INTERFACE,
207753a5a1b3Sopenharmony_ci                                                      signals[SIGNAL_SINK_REMOVED].name));
207853a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
207953a5a1b3Sopenharmony_ci
208053a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
208153a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
208253a5a1b3Sopenharmony_ci
208353a5a1b3Sopenharmony_ci    pa_dbusiface_device_free(d);
208453a5a1b3Sopenharmony_ci
208553a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
208653a5a1b3Sopenharmony_ci}
208753a5a1b3Sopenharmony_ci
208853a5a1b3Sopenharmony_cistatic pa_hook_result_t source_put_cb(void *hook_data, void *call_data, void *slot_data) {
208953a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
209053a5a1b3Sopenharmony_ci    pa_source *s = call_data;
209153a5a1b3Sopenharmony_ci
209253a5a1b3Sopenharmony_ci    pa_assert(c);
209353a5a1b3Sopenharmony_ci    pa_assert(s);
209453a5a1b3Sopenharmony_ci
209553a5a1b3Sopenharmony_ci    /* We may have alredy encountered this source, because if the new source
209653a5a1b3Sopenharmony_ci     * was chosen as the default source, the default source change hook was
209753a5a1b3Sopenharmony_ci     * fired first, and we saw the source in default_source_changed_cb(). */
209853a5a1b3Sopenharmony_ci    if (pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(s->index)))
209953a5a1b3Sopenharmony_ci        return PA_HOOK_OK;
210053a5a1b3Sopenharmony_ci
210153a5a1b3Sopenharmony_ci    create_dbus_object_for_source(c, s);
210253a5a1b3Sopenharmony_ci
210353a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
210453a5a1b3Sopenharmony_ci}
210553a5a1b3Sopenharmony_ci
210653a5a1b3Sopenharmony_cistatic pa_hook_result_t source_unlink_cb(void *hook_data, void *call_data, void *slot_data) {
210753a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
210853a5a1b3Sopenharmony_ci    pa_source *s = call_data;
210953a5a1b3Sopenharmony_ci    pa_dbusiface_device *d = NULL;
211053a5a1b3Sopenharmony_ci    const char *object_path = NULL;
211153a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
211253a5a1b3Sopenharmony_ci
211353a5a1b3Sopenharmony_ci    pa_assert(c);
211453a5a1b3Sopenharmony_ci    pa_assert(s);
211553a5a1b3Sopenharmony_ci
211653a5a1b3Sopenharmony_ci    pa_assert_se(d = pa_hashmap_remove(c->sources_by_index, PA_UINT32_TO_PTR(s->index)));
211753a5a1b3Sopenharmony_ci    object_path = pa_dbusiface_device_get_path(d);
211853a5a1b3Sopenharmony_ci    pa_assert_se(pa_hashmap_remove(c->sources_by_path, object_path));
211953a5a1b3Sopenharmony_ci
212053a5a1b3Sopenharmony_ci    pa_assert_se(signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
212153a5a1b3Sopenharmony_ci                                                      PA_DBUS_CORE_INTERFACE,
212253a5a1b3Sopenharmony_ci                                                      signals[SIGNAL_SOURCE_REMOVED].name));
212353a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
212453a5a1b3Sopenharmony_ci
212553a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
212653a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
212753a5a1b3Sopenharmony_ci
212853a5a1b3Sopenharmony_ci    pa_dbusiface_device_free(d);
212953a5a1b3Sopenharmony_ci
213053a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
213153a5a1b3Sopenharmony_ci}
213253a5a1b3Sopenharmony_ci
213353a5a1b3Sopenharmony_cistatic pa_hook_result_t extension_registered_cb(void *hook_data, void *call_data, void *slot_data) {
213453a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
213553a5a1b3Sopenharmony_ci    const char *ext_name = call_data;
213653a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
213753a5a1b3Sopenharmony_ci
213853a5a1b3Sopenharmony_ci    pa_assert(c);
213953a5a1b3Sopenharmony_ci    pa_assert(ext_name);
214053a5a1b3Sopenharmony_ci
214153a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
214253a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
214353a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_NEW_EXTENSION].name)));
214453a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID));
214553a5a1b3Sopenharmony_ci
214653a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
214753a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
214853a5a1b3Sopenharmony_ci
214953a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
215053a5a1b3Sopenharmony_ci}
215153a5a1b3Sopenharmony_ci
215253a5a1b3Sopenharmony_cistatic pa_hook_result_t extension_unregistered_cb(void *hook_data, void *call_data, void *slot_data) {
215353a5a1b3Sopenharmony_ci    pa_dbusiface_core *c = slot_data;
215453a5a1b3Sopenharmony_ci    const char *ext_name = call_data;
215553a5a1b3Sopenharmony_ci    DBusMessage *signal_msg = NULL;
215653a5a1b3Sopenharmony_ci
215753a5a1b3Sopenharmony_ci    pa_assert(c);
215853a5a1b3Sopenharmony_ci    pa_assert(ext_name);
215953a5a1b3Sopenharmony_ci
216053a5a1b3Sopenharmony_ci    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH,
216153a5a1b3Sopenharmony_ci                                                       PA_DBUS_CORE_INTERFACE,
216253a5a1b3Sopenharmony_ci                                                       signals[SIGNAL_EXTENSION_REMOVED].name)));
216353a5a1b3Sopenharmony_ci    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID));
216453a5a1b3Sopenharmony_ci
216553a5a1b3Sopenharmony_ci    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg);
216653a5a1b3Sopenharmony_ci    dbus_message_unref(signal_msg);
216753a5a1b3Sopenharmony_ci
216853a5a1b3Sopenharmony_ci    return PA_HOOK_OK;
216953a5a1b3Sopenharmony_ci}
217053a5a1b3Sopenharmony_ci
217153a5a1b3Sopenharmony_cipa_dbusiface_core *pa_dbusiface_core_new(pa_core *core) {
217253a5a1b3Sopenharmony_ci    pa_dbusiface_core *c;
217353a5a1b3Sopenharmony_ci    pa_card *card;
217453a5a1b3Sopenharmony_ci    pa_sink *sink;
217553a5a1b3Sopenharmony_ci    pa_source *source;
217653a5a1b3Sopenharmony_ci    pa_dbusiface_device *device;
217753a5a1b3Sopenharmony_ci    pa_sink_input *sink_input;
217853a5a1b3Sopenharmony_ci    pa_source_output *source_output;
217953a5a1b3Sopenharmony_ci    pa_scache_entry *sample;
218053a5a1b3Sopenharmony_ci    pa_module *module;
218153a5a1b3Sopenharmony_ci    pa_client *client;
218253a5a1b3Sopenharmony_ci    uint32_t idx;
218353a5a1b3Sopenharmony_ci
218453a5a1b3Sopenharmony_ci    pa_assert(core);
218553a5a1b3Sopenharmony_ci
218653a5a1b3Sopenharmony_ci    c = pa_xnew(pa_dbusiface_core, 1);
218753a5a1b3Sopenharmony_ci    c->core = core;
218853a5a1b3Sopenharmony_ci    c->dbus_protocol = pa_dbus_protocol_get(core);
218953a5a1b3Sopenharmony_ci    c->cards = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_card_free);
219053a5a1b3Sopenharmony_ci    c->sinks_by_index = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
219153a5a1b3Sopenharmony_ci                                            (pa_free_cb_t) pa_dbusiface_device_free);
219253a5a1b3Sopenharmony_ci    c->sinks_by_path = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
219353a5a1b3Sopenharmony_ci    c->sources_by_index = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
219453a5a1b3Sopenharmony_ci                                              (pa_free_cb_t) pa_dbusiface_device_free);
219553a5a1b3Sopenharmony_ci    c->sources_by_path = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
219653a5a1b3Sopenharmony_ci    c->playback_streams = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
219753a5a1b3Sopenharmony_ci                                              (pa_free_cb_t) pa_dbusiface_stream_free);
219853a5a1b3Sopenharmony_ci    c->record_streams = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
219953a5a1b3Sopenharmony_ci                                            (pa_free_cb_t) pa_dbusiface_stream_free);
220053a5a1b3Sopenharmony_ci    c->samples = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_sample_free);
220153a5a1b3Sopenharmony_ci    c->modules = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_module_free);
220253a5a1b3Sopenharmony_ci    c->clients = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_client_free);
220353a5a1b3Sopenharmony_ci    c->fallback_sink = core->default_sink;
220453a5a1b3Sopenharmony_ci    c->fallback_source = core->default_source;
220553a5a1b3Sopenharmony_ci    c->default_sink_changed_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_DEFAULT_SINK_CHANGED],
220653a5a1b3Sopenharmony_ci                                                   PA_HOOK_NORMAL, default_sink_changed_cb, c);
220753a5a1b3Sopenharmony_ci    c->default_source_changed_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED],
220853a5a1b3Sopenharmony_ci                                                     PA_HOOK_NORMAL, default_source_changed_cb, c);
220953a5a1b3Sopenharmony_ci    c->module_new_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_MODULE_NEW],
221053a5a1b3Sopenharmony_ci                                         PA_HOOK_NORMAL, module_new_cb, c);
221153a5a1b3Sopenharmony_ci    c->module_removed_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_MODULE_UNLINK],
221253a5a1b3Sopenharmony_ci                                             PA_HOOK_NORMAL, module_removed_cb, c);
221353a5a1b3Sopenharmony_ci    c->sample_cache_new_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SAMPLE_CACHE_NEW],
221453a5a1b3Sopenharmony_ci                                               PA_HOOK_NORMAL, sample_cache_new_cb, c);
221553a5a1b3Sopenharmony_ci    c->sample_cache_removed_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SAMPLE_CACHE_UNLINK],
221653a5a1b3Sopenharmony_ci                                                   PA_HOOK_NORMAL, sample_cache_removed_cb, c);
221753a5a1b3Sopenharmony_ci    c->card_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CARD_PUT],
221853a5a1b3Sopenharmony_ci                                       PA_HOOK_NORMAL, card_put_cb, c);
221953a5a1b3Sopenharmony_ci    c->card_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CARD_UNLINK],
222053a5a1b3Sopenharmony_ci                                          PA_HOOK_NORMAL, card_unlink_cb, c);
222153a5a1b3Sopenharmony_ci    c->sink_input_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT],
222253a5a1b3Sopenharmony_ci                                             PA_HOOK_NORMAL, sink_input_put_cb, c);
222353a5a1b3Sopenharmony_ci    c->sink_input_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK],
222453a5a1b3Sopenharmony_ci                                                PA_HOOK_NORMAL, sink_input_unlink_cb, c);
222553a5a1b3Sopenharmony_ci    c->source_output_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT],
222653a5a1b3Sopenharmony_ci                                                PA_HOOK_NORMAL, source_output_put_cb, c);
222753a5a1b3Sopenharmony_ci    c->source_output_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK],
222853a5a1b3Sopenharmony_ci                                                   PA_HOOK_NORMAL, source_output_unlink_cb, c);
222953a5a1b3Sopenharmony_ci    c->client_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CLIENT_PUT],
223053a5a1b3Sopenharmony_ci                                         PA_HOOK_NORMAL, client_put_cb, c);
223153a5a1b3Sopenharmony_ci    c->client_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CLIENT_UNLINK],
223253a5a1b3Sopenharmony_ci                                            PA_HOOK_NORMAL, client_unlink_cb, c);
223353a5a1b3Sopenharmony_ci    c->sink_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_NORMAL, sink_put_cb, c);
223453a5a1b3Sopenharmony_ci    c->sink_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_NORMAL, sink_unlink_cb, c);
223553a5a1b3Sopenharmony_ci    c->source_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_NORMAL, source_put_cb, c);
223653a5a1b3Sopenharmony_ci    c->source_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_NORMAL, source_unlink_cb, c);
223753a5a1b3Sopenharmony_ci    c->extension_registered_slot = pa_dbus_protocol_hook_connect(c->dbus_protocol,
223853a5a1b3Sopenharmony_ci                                                                 PA_DBUS_PROTOCOL_HOOK_EXTENSION_REGISTERED,
223953a5a1b3Sopenharmony_ci                                                                 PA_HOOK_NORMAL,
224053a5a1b3Sopenharmony_ci                                                                 extension_registered_cb,
224153a5a1b3Sopenharmony_ci                                                                 c);
224253a5a1b3Sopenharmony_ci    c->extension_unregistered_slot = pa_dbus_protocol_hook_connect(c->dbus_protocol,
224353a5a1b3Sopenharmony_ci                                                                   PA_DBUS_PROTOCOL_HOOK_EXTENSION_UNREGISTERED,
224453a5a1b3Sopenharmony_ci                                                                   PA_HOOK_NORMAL,
224553a5a1b3Sopenharmony_ci                                                                   extension_unregistered_cb,
224653a5a1b3Sopenharmony_ci                                                                   c);
224753a5a1b3Sopenharmony_ci    c->memstats = pa_dbusiface_memstats_new(c, core);
224853a5a1b3Sopenharmony_ci
224953a5a1b3Sopenharmony_ci    if (c->fallback_sink)
225053a5a1b3Sopenharmony_ci        pa_sink_ref(c->fallback_sink);
225153a5a1b3Sopenharmony_ci    if (c->fallback_source)
225253a5a1b3Sopenharmony_ci        pa_source_ref(c->fallback_source);
225353a5a1b3Sopenharmony_ci
225453a5a1b3Sopenharmony_ci    PA_IDXSET_FOREACH(card, core->cards, idx)
225553a5a1b3Sopenharmony_ci        pa_hashmap_put(c->cards, PA_UINT32_TO_PTR(idx), pa_dbusiface_card_new(c, card));
225653a5a1b3Sopenharmony_ci
225753a5a1b3Sopenharmony_ci    PA_IDXSET_FOREACH(sink, core->sinks, idx) {
225853a5a1b3Sopenharmony_ci        device = pa_dbusiface_device_new_sink(c, sink);
225953a5a1b3Sopenharmony_ci        pa_hashmap_put(c->sinks_by_index, PA_UINT32_TO_PTR(idx), device);
226053a5a1b3Sopenharmony_ci        pa_hashmap_put(c->sinks_by_path, (char *) pa_dbusiface_device_get_path(device), device);
226153a5a1b3Sopenharmony_ci    }
226253a5a1b3Sopenharmony_ci
226353a5a1b3Sopenharmony_ci    PA_IDXSET_FOREACH(source, core->sources, idx) {
226453a5a1b3Sopenharmony_ci        device = pa_dbusiface_device_new_source(c, source);
226553a5a1b3Sopenharmony_ci        pa_hashmap_put(c->sources_by_index, PA_UINT32_TO_PTR(idx), device);
226653a5a1b3Sopenharmony_ci        pa_hashmap_put(c->sources_by_path, (char *) pa_dbusiface_device_get_path(device), device);
226753a5a1b3Sopenharmony_ci    }
226853a5a1b3Sopenharmony_ci
226953a5a1b3Sopenharmony_ci    PA_IDXSET_FOREACH(sink_input, core->sink_inputs, idx)
227053a5a1b3Sopenharmony_ci        pa_hashmap_put(c->playback_streams, PA_UINT32_TO_PTR(idx), pa_dbusiface_stream_new_playback(c, sink_input));
227153a5a1b3Sopenharmony_ci
227253a5a1b3Sopenharmony_ci    PA_IDXSET_FOREACH(source_output, core->source_outputs, idx)
227353a5a1b3Sopenharmony_ci        pa_hashmap_put(c->record_streams, PA_UINT32_TO_PTR(idx), pa_dbusiface_stream_new_record(c, source_output));
227453a5a1b3Sopenharmony_ci
227553a5a1b3Sopenharmony_ci    PA_IDXSET_FOREACH(sample, core->scache, idx)
227653a5a1b3Sopenharmony_ci        pa_hashmap_put(c->samples, PA_UINT32_TO_PTR(idx), pa_dbusiface_sample_new(c, sample));
227753a5a1b3Sopenharmony_ci
227853a5a1b3Sopenharmony_ci    PA_IDXSET_FOREACH(module, core->modules, idx)
227953a5a1b3Sopenharmony_ci        pa_hashmap_put(c->modules, PA_UINT32_TO_PTR(idx), pa_dbusiface_module_new(module));
228053a5a1b3Sopenharmony_ci
228153a5a1b3Sopenharmony_ci    PA_IDXSET_FOREACH(client, core->clients, idx)
228253a5a1b3Sopenharmony_ci        pa_hashmap_put(c->clients, PA_UINT32_TO_PTR(idx), pa_dbusiface_client_new(c, client));
228353a5a1b3Sopenharmony_ci
228453a5a1b3Sopenharmony_ci    pa_assert_se(pa_dbus_protocol_add_interface(c->dbus_protocol, PA_DBUS_CORE_OBJECT_PATH, &core_interface_info, c) >= 0);
228553a5a1b3Sopenharmony_ci
228653a5a1b3Sopenharmony_ci    return c;
228753a5a1b3Sopenharmony_ci}
228853a5a1b3Sopenharmony_ci
228953a5a1b3Sopenharmony_civoid pa_dbusiface_core_free(pa_dbusiface_core *c) {
229053a5a1b3Sopenharmony_ci    pa_assert(c);
229153a5a1b3Sopenharmony_ci
229253a5a1b3Sopenharmony_ci    pa_assert_se(pa_dbus_protocol_remove_interface(c->dbus_protocol, PA_DBUS_CORE_OBJECT_PATH, core_interface_info.name) >= 0);
229353a5a1b3Sopenharmony_ci
229453a5a1b3Sopenharmony_ci    /* Note that the order of freeing is important below.
229553a5a1b3Sopenharmony_ci     * Do not change it for the sake of tidiness without checking! */
229653a5a1b3Sopenharmony_ci    pa_hashmap_free(c->cards);
229753a5a1b3Sopenharmony_ci    pa_hashmap_free(c->sinks_by_path);
229853a5a1b3Sopenharmony_ci    pa_hashmap_free(c->sinks_by_index);
229953a5a1b3Sopenharmony_ci    pa_hashmap_free(c->sources_by_path);
230053a5a1b3Sopenharmony_ci    pa_hashmap_free(c->sources_by_index);
230153a5a1b3Sopenharmony_ci    pa_hashmap_free(c->playback_streams);
230253a5a1b3Sopenharmony_ci    pa_hashmap_free(c->record_streams);
230353a5a1b3Sopenharmony_ci    pa_hashmap_free(c->samples);
230453a5a1b3Sopenharmony_ci    pa_hashmap_free(c->modules);
230553a5a1b3Sopenharmony_ci    pa_hashmap_free(c->clients);
230653a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->module_new_slot);
230753a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->module_removed_slot);
230853a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->default_sink_changed_slot);
230953a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->default_source_changed_slot);
231053a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->sample_cache_new_slot);
231153a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->sample_cache_removed_slot);
231253a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->card_put_slot);
231353a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->card_unlink_slot);
231453a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->sink_input_put_slot);
231553a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->sink_input_unlink_slot);
231653a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->source_output_put_slot);
231753a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->source_output_unlink_slot);
231853a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->client_put_slot);
231953a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->client_unlink_slot);
232053a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->sink_put_slot);
232153a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->sink_unlink_slot);
232253a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->source_put_slot);
232353a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->source_unlink_slot);
232453a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->extension_registered_slot);
232553a5a1b3Sopenharmony_ci    pa_hook_slot_free(c->extension_unregistered_slot);
232653a5a1b3Sopenharmony_ci    pa_dbusiface_memstats_free(c->memstats);
232753a5a1b3Sopenharmony_ci
232853a5a1b3Sopenharmony_ci    if (c->fallback_sink)
232953a5a1b3Sopenharmony_ci        pa_sink_unref(c->fallback_sink);
233053a5a1b3Sopenharmony_ci    if (c->fallback_source)
233153a5a1b3Sopenharmony_ci        pa_source_unref(c->fallback_source);
233253a5a1b3Sopenharmony_ci
233353a5a1b3Sopenharmony_ci    pa_dbus_protocol_unref(c->dbus_protocol);
233453a5a1b3Sopenharmony_ci
233553a5a1b3Sopenharmony_ci    pa_xfree(c);
233653a5a1b3Sopenharmony_ci}
233753a5a1b3Sopenharmony_ci
233853a5a1b3Sopenharmony_ciconst char *pa_dbusiface_core_get_card_path(pa_dbusiface_core *c, const pa_card *card) {
233953a5a1b3Sopenharmony_ci    pa_assert(c);
234053a5a1b3Sopenharmony_ci    pa_assert(card);
234153a5a1b3Sopenharmony_ci
234253a5a1b3Sopenharmony_ci    return pa_dbusiface_card_get_path(pa_hashmap_get(c->cards, PA_UINT32_TO_PTR(card->index)));
234353a5a1b3Sopenharmony_ci}
234453a5a1b3Sopenharmony_ci
234553a5a1b3Sopenharmony_ciconst char *pa_dbusiface_core_get_sink_path(pa_dbusiface_core *c, const pa_sink *sink) {
234653a5a1b3Sopenharmony_ci    pa_assert(c);
234753a5a1b3Sopenharmony_ci    pa_assert(sink);
234853a5a1b3Sopenharmony_ci
234953a5a1b3Sopenharmony_ci    return pa_dbusiface_device_get_path(pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(sink->index)));
235053a5a1b3Sopenharmony_ci}
235153a5a1b3Sopenharmony_ci
235253a5a1b3Sopenharmony_ciconst char *pa_dbusiface_core_get_source_path(pa_dbusiface_core *c, const pa_source *source) {
235353a5a1b3Sopenharmony_ci    pa_assert(c);
235453a5a1b3Sopenharmony_ci    pa_assert(source);
235553a5a1b3Sopenharmony_ci
235653a5a1b3Sopenharmony_ci    return pa_dbusiface_device_get_path(pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(source->index)));
235753a5a1b3Sopenharmony_ci}
235853a5a1b3Sopenharmony_ci
235953a5a1b3Sopenharmony_ciconst char *pa_dbusiface_core_get_playback_stream_path(pa_dbusiface_core *c, const pa_sink_input *sink_input) {
236053a5a1b3Sopenharmony_ci    pa_assert(c);
236153a5a1b3Sopenharmony_ci    pa_assert(sink_input);
236253a5a1b3Sopenharmony_ci
236353a5a1b3Sopenharmony_ci    return pa_dbusiface_stream_get_path(pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(sink_input->index)));
236453a5a1b3Sopenharmony_ci}
236553a5a1b3Sopenharmony_ci
236653a5a1b3Sopenharmony_ciconst char *pa_dbusiface_core_get_record_stream_path(pa_dbusiface_core *c, const pa_source_output *source_output) {
236753a5a1b3Sopenharmony_ci    pa_assert(c);
236853a5a1b3Sopenharmony_ci    pa_assert(source_output);
236953a5a1b3Sopenharmony_ci
237053a5a1b3Sopenharmony_ci    return pa_dbusiface_stream_get_path(pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(source_output->index)));
237153a5a1b3Sopenharmony_ci}
237253a5a1b3Sopenharmony_ci
237353a5a1b3Sopenharmony_ciconst char *pa_dbusiface_core_get_module_path(pa_dbusiface_core *c, const pa_module *module) {
237453a5a1b3Sopenharmony_ci    pa_assert(c);
237553a5a1b3Sopenharmony_ci    pa_assert(module);
237653a5a1b3Sopenharmony_ci
237753a5a1b3Sopenharmony_ci    return pa_dbusiface_module_get_path(pa_hashmap_get(c->modules, PA_UINT32_TO_PTR(module->index)));
237853a5a1b3Sopenharmony_ci}
237953a5a1b3Sopenharmony_ci
238053a5a1b3Sopenharmony_ciconst char *pa_dbusiface_core_get_client_path(pa_dbusiface_core *c, const pa_client *client) {
238153a5a1b3Sopenharmony_ci    pa_assert(c);
238253a5a1b3Sopenharmony_ci    pa_assert(client);
238353a5a1b3Sopenharmony_ci
238453a5a1b3Sopenharmony_ci    return pa_dbusiface_client_get_path(pa_hashmap_get(c->clients, PA_UINT32_TO_PTR(client->index)));
238553a5a1b3Sopenharmony_ci}
238653a5a1b3Sopenharmony_ci
238753a5a1b3Sopenharmony_cipa_sink *pa_dbusiface_core_get_sink(pa_dbusiface_core *c, const char *object_path) {
238853a5a1b3Sopenharmony_ci    pa_dbusiface_device *device = NULL;
238953a5a1b3Sopenharmony_ci
239053a5a1b3Sopenharmony_ci    pa_assert(c);
239153a5a1b3Sopenharmony_ci    pa_assert(object_path);
239253a5a1b3Sopenharmony_ci
239353a5a1b3Sopenharmony_ci    device = pa_hashmap_get(c->sinks_by_path, object_path);
239453a5a1b3Sopenharmony_ci
239553a5a1b3Sopenharmony_ci    if (device)
239653a5a1b3Sopenharmony_ci        return pa_dbusiface_device_get_sink(device);
239753a5a1b3Sopenharmony_ci    else
239853a5a1b3Sopenharmony_ci        return NULL;
239953a5a1b3Sopenharmony_ci}
240053a5a1b3Sopenharmony_ci
240153a5a1b3Sopenharmony_cipa_source *pa_dbusiface_core_get_source(pa_dbusiface_core *c, const char *object_path) {
240253a5a1b3Sopenharmony_ci    pa_dbusiface_device *device = NULL;
240353a5a1b3Sopenharmony_ci
240453a5a1b3Sopenharmony_ci    pa_assert(c);
240553a5a1b3Sopenharmony_ci    pa_assert(object_path);
240653a5a1b3Sopenharmony_ci
240753a5a1b3Sopenharmony_ci    device = pa_hashmap_get(c->sources_by_path, object_path);
240853a5a1b3Sopenharmony_ci
240953a5a1b3Sopenharmony_ci    if (device)
241053a5a1b3Sopenharmony_ci        return pa_dbusiface_device_get_source(device);
241153a5a1b3Sopenharmony_ci    else
241253a5a1b3Sopenharmony_ci        return NULL;
241353a5a1b3Sopenharmony_ci}
2414