153a5a1b3Sopenharmony_ci/***
253a5a1b3Sopenharmony_ci  This file is part of PulseAudio.
353a5a1b3Sopenharmony_ci
453a5a1b3Sopenharmony_ci  Copyright 2009 Tanu Kaskinen
553a5a1b3Sopenharmony_ci
653a5a1b3Sopenharmony_ci  PulseAudio is free software; you can redistribute it and/or modify
753a5a1b3Sopenharmony_ci  it under the terms of the GNU Lesser General Public License as published
853a5a1b3Sopenharmony_ci  by the Free Software Foundation; either version 2.1 of the License,
953a5a1b3Sopenharmony_ci  or (at your option) any later version.
1053a5a1b3Sopenharmony_ci
1153a5a1b3Sopenharmony_ci  PulseAudio is distributed in the hope that it will be useful, but
1253a5a1b3Sopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1353a5a1b3Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1453a5a1b3Sopenharmony_ci  General Public License for more details.
1553a5a1b3Sopenharmony_ci
1653a5a1b3Sopenharmony_ci  You should have received a copy of the GNU Lesser General Public License
1753a5a1b3Sopenharmony_ci  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
1853a5a1b3Sopenharmony_ci***/
1953a5a1b3Sopenharmony_ci
2053a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H
2153a5a1b3Sopenharmony_ci#include <config.h>
2253a5a1b3Sopenharmony_ci#endif
2353a5a1b3Sopenharmony_ci
2453a5a1b3Sopenharmony_ci#include <dbus/dbus.h>
2553a5a1b3Sopenharmony_ci
2653a5a1b3Sopenharmony_ci#include <pulse/client-conf.h>
2753a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h>
2853a5a1b3Sopenharmony_ci
2953a5a1b3Sopenharmony_ci#include <pulsecore/core.h>
3053a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h>
3153a5a1b3Sopenharmony_ci#include <pulsecore/dbus-shared.h>
3253a5a1b3Sopenharmony_ci#include <pulsecore/macro.h>
3353a5a1b3Sopenharmony_ci#include <pulsecore/protocol-dbus.h>
3453a5a1b3Sopenharmony_ci
3553a5a1b3Sopenharmony_ci#include "server-lookup.h"
3653a5a1b3Sopenharmony_ci
3753a5a1b3Sopenharmony_ci#define OBJECT_PATH "/org/pulseaudio/server_lookup1"
3853a5a1b3Sopenharmony_ci#define INTERFACE "org.PulseAudio.ServerLookup1"
3953a5a1b3Sopenharmony_ci
4053a5a1b3Sopenharmony_cistruct pa_dbusobj_server_lookup {
4153a5a1b3Sopenharmony_ci    pa_core *core;
4253a5a1b3Sopenharmony_ci    pa_dbus_connection *conn;
4353a5a1b3Sopenharmony_ci    bool path_registered;
4453a5a1b3Sopenharmony_ci};
4553a5a1b3Sopenharmony_ci
4653a5a1b3Sopenharmony_cistatic const char introspection[] =
4753a5a1b3Sopenharmony_ci    DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
4853a5a1b3Sopenharmony_ci    "<node>"
4953a5a1b3Sopenharmony_ci    " <!-- If you are looking for documentation make sure to check out\n"
5053a5a1b3Sopenharmony_ci    "      http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/Clients/DBus/ -->\n"
5153a5a1b3Sopenharmony_ci    " <interface name=\"" INTERFACE "\">\n"
5253a5a1b3Sopenharmony_ci    "  <property name=\"Address\" type=\"s\" access=\"read\"/>\n"
5353a5a1b3Sopenharmony_ci    " </interface>\n"
5453a5a1b3Sopenharmony_ci    " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n"
5553a5a1b3Sopenharmony_ci    "  <method name=\"Introspect\">\n"
5653a5a1b3Sopenharmony_ci    "   <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
5753a5a1b3Sopenharmony_ci    "  </method>\n"
5853a5a1b3Sopenharmony_ci    " </interface>\n"
5953a5a1b3Sopenharmony_ci    " <interface name=\"" DBUS_INTERFACE_PROPERTIES "\">\n"
6053a5a1b3Sopenharmony_ci    "  <method name=\"Get\">\n"
6153a5a1b3Sopenharmony_ci    "   <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n"
6253a5a1b3Sopenharmony_ci    "   <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n"
6353a5a1b3Sopenharmony_ci    "   <arg name=\"value\" type=\"v\" direction=\"out\"/>\n"
6453a5a1b3Sopenharmony_ci    "  </method>\n"
6553a5a1b3Sopenharmony_ci    "  <method name=\"Set\">\n"
6653a5a1b3Sopenharmony_ci    "   <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n"
6753a5a1b3Sopenharmony_ci    "   <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n"
6853a5a1b3Sopenharmony_ci    "   <arg name=\"value\" type=\"v\" direction=\"in\"/>\n"
6953a5a1b3Sopenharmony_ci    "  </method>\n"
7053a5a1b3Sopenharmony_ci    "  <method name=\"GetAll\">\n"
7153a5a1b3Sopenharmony_ci    "   <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n"
7253a5a1b3Sopenharmony_ci    "   <arg name=\"props\" type=\"a{sv}\" direction=\"out\"/>\n"
7353a5a1b3Sopenharmony_ci    "  </method>\n"
7453a5a1b3Sopenharmony_ci    " </interface>\n"
7553a5a1b3Sopenharmony_ci    "</node>\n";
7653a5a1b3Sopenharmony_ci
7753a5a1b3Sopenharmony_cistatic void unregister_cb(DBusConnection *conn, void *user_data) {
7853a5a1b3Sopenharmony_ci    pa_dbusobj_server_lookup *sl = user_data;
7953a5a1b3Sopenharmony_ci
8053a5a1b3Sopenharmony_ci    pa_assert(sl);
8153a5a1b3Sopenharmony_ci    pa_assert(sl->path_registered);
8253a5a1b3Sopenharmony_ci
8353a5a1b3Sopenharmony_ci    sl->path_registered = false;
8453a5a1b3Sopenharmony_ci}
8553a5a1b3Sopenharmony_ci
8653a5a1b3Sopenharmony_cistatic DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) {
8753a5a1b3Sopenharmony_ci    DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
8853a5a1b3Sopenharmony_ci    const char *i = introspection;
8953a5a1b3Sopenharmony_ci    DBusMessage *reply = NULL;
9053a5a1b3Sopenharmony_ci
9153a5a1b3Sopenharmony_ci    pa_assert(conn);
9253a5a1b3Sopenharmony_ci    pa_assert(msg);
9353a5a1b3Sopenharmony_ci
9453a5a1b3Sopenharmony_ci    if (!(reply = dbus_message_new_method_return(msg))) {
9553a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
9653a5a1b3Sopenharmony_ci        goto finish;
9753a5a1b3Sopenharmony_ci    }
9853a5a1b3Sopenharmony_ci    if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &i, DBUS_TYPE_INVALID)) {
9953a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
10053a5a1b3Sopenharmony_ci        goto finish;
10153a5a1b3Sopenharmony_ci    }
10253a5a1b3Sopenharmony_ci    if (!dbus_connection_send(conn, reply, NULL)) {
10353a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_NEED_MEMORY;
10453a5a1b3Sopenharmony_ci        goto finish;
10553a5a1b3Sopenharmony_ci    }
10653a5a1b3Sopenharmony_ci
10753a5a1b3Sopenharmony_cifinish:
10853a5a1b3Sopenharmony_ci    if (reply)
10953a5a1b3Sopenharmony_ci        dbus_message_unref(reply);
11053a5a1b3Sopenharmony_ci
11153a5a1b3Sopenharmony_ci    return r;
11253a5a1b3Sopenharmony_ci}
11353a5a1b3Sopenharmony_ci
11453a5a1b3Sopenharmony_cienum get_address_result_t {
11553a5a1b3Sopenharmony_ci    SUCCESS,
11653a5a1b3Sopenharmony_ci    SERVER_FROM_TYPE_FAILED
11753a5a1b3Sopenharmony_ci};
11853a5a1b3Sopenharmony_ci
11953a5a1b3Sopenharmony_ci/* Caller frees the returned address. */
12053a5a1b3Sopenharmony_cistatic enum get_address_result_t get_address(pa_server_type_t server_type, char **address) {
12153a5a1b3Sopenharmony_ci    enum get_address_result_t r = SUCCESS;
12253a5a1b3Sopenharmony_ci    pa_client_conf *conf = pa_client_conf_new();
12353a5a1b3Sopenharmony_ci
12453a5a1b3Sopenharmony_ci    *address = NULL;
12553a5a1b3Sopenharmony_ci
12653a5a1b3Sopenharmony_ci    pa_client_conf_load(conf, false, false);
12753a5a1b3Sopenharmony_ci
12853a5a1b3Sopenharmony_ci    if (conf->default_dbus_server)
12953a5a1b3Sopenharmony_ci        *address = pa_xstrdup(conf->default_dbus_server);
13053a5a1b3Sopenharmony_ci    else if (!(*address = pa_get_dbus_address_from_server_type(server_type))) {
13153a5a1b3Sopenharmony_ci        r = SERVER_FROM_TYPE_FAILED;
13253a5a1b3Sopenharmony_ci        goto finish;
13353a5a1b3Sopenharmony_ci    }
13453a5a1b3Sopenharmony_ci
13553a5a1b3Sopenharmony_cifinish:
13653a5a1b3Sopenharmony_ci    pa_client_conf_free(conf);
13753a5a1b3Sopenharmony_ci    return r;
13853a5a1b3Sopenharmony_ci}
13953a5a1b3Sopenharmony_ci
14053a5a1b3Sopenharmony_cistatic DBusHandlerResult handle_get_address(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) {
14153a5a1b3Sopenharmony_ci    DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
14253a5a1b3Sopenharmony_ci    DBusMessage *reply = NULL;
14353a5a1b3Sopenharmony_ci    char *address = NULL;
14453a5a1b3Sopenharmony_ci    DBusMessageIter msg_iter;
14553a5a1b3Sopenharmony_ci    DBusMessageIter variant_iter;
14653a5a1b3Sopenharmony_ci
14753a5a1b3Sopenharmony_ci    pa_assert(conn);
14853a5a1b3Sopenharmony_ci    pa_assert(msg);
14953a5a1b3Sopenharmony_ci    pa_assert(sl);
15053a5a1b3Sopenharmony_ci
15153a5a1b3Sopenharmony_ci    switch (get_address(sl->core->server_type, &address)) {
15253a5a1b3Sopenharmony_ci        case SUCCESS:
15353a5a1b3Sopenharmony_ci            if (!(reply = dbus_message_new_method_return(msg))) {
15453a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
15553a5a1b3Sopenharmony_ci                goto finish;
15653a5a1b3Sopenharmony_ci            }
15753a5a1b3Sopenharmony_ci            dbus_message_iter_init_append(reply, &msg_iter);
15853a5a1b3Sopenharmony_ci            if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) {
15953a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
16053a5a1b3Sopenharmony_ci                goto finish;
16153a5a1b3Sopenharmony_ci            }
16253a5a1b3Sopenharmony_ci            if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &address)) {
16353a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
16453a5a1b3Sopenharmony_ci                goto finish;
16553a5a1b3Sopenharmony_ci            }
16653a5a1b3Sopenharmony_ci            if (!dbus_message_iter_close_container(&msg_iter, &variant_iter)) {
16753a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
16853a5a1b3Sopenharmony_ci                goto finish;
16953a5a1b3Sopenharmony_ci            }
17053a5a1b3Sopenharmony_ci            if (!dbus_connection_send(conn, reply, NULL)) {
17153a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
17253a5a1b3Sopenharmony_ci                goto finish;
17353a5a1b3Sopenharmony_ci            }
17453a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_HANDLED;
17553a5a1b3Sopenharmony_ci            goto finish;
17653a5a1b3Sopenharmony_ci
17753a5a1b3Sopenharmony_ci        case SERVER_FROM_TYPE_FAILED:
17853a5a1b3Sopenharmony_ci            if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) {
17953a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
18053a5a1b3Sopenharmony_ci                goto finish;
18153a5a1b3Sopenharmony_ci            }
18253a5a1b3Sopenharmony_ci            if (!dbus_connection_send(conn, reply, NULL)) {
18353a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
18453a5a1b3Sopenharmony_ci                goto finish;
18553a5a1b3Sopenharmony_ci            }
18653a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_HANDLED;
18753a5a1b3Sopenharmony_ci            goto finish;
18853a5a1b3Sopenharmony_ci
18953a5a1b3Sopenharmony_ci        default:
19053a5a1b3Sopenharmony_ci            pa_assert_not_reached();
19153a5a1b3Sopenharmony_ci    }
19253a5a1b3Sopenharmony_ci
19353a5a1b3Sopenharmony_cifinish:
19453a5a1b3Sopenharmony_ci    pa_xfree(address);
19553a5a1b3Sopenharmony_ci    if (reply)
19653a5a1b3Sopenharmony_ci        dbus_message_unref(reply);
19753a5a1b3Sopenharmony_ci
19853a5a1b3Sopenharmony_ci    return r;
19953a5a1b3Sopenharmony_ci}
20053a5a1b3Sopenharmony_ci
20153a5a1b3Sopenharmony_cistatic DBusHandlerResult handle_get(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) {
20253a5a1b3Sopenharmony_ci    DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
20353a5a1b3Sopenharmony_ci    const char* interface;
20453a5a1b3Sopenharmony_ci    const char* property;
20553a5a1b3Sopenharmony_ci    DBusMessage *reply = NULL;
20653a5a1b3Sopenharmony_ci
20753a5a1b3Sopenharmony_ci    pa_assert(conn);
20853a5a1b3Sopenharmony_ci    pa_assert(msg);
20953a5a1b3Sopenharmony_ci    pa_assert(sl);
21053a5a1b3Sopenharmony_ci
21153a5a1b3Sopenharmony_ci    if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
21253a5a1b3Sopenharmony_ci        if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) {
21353a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
21453a5a1b3Sopenharmony_ci            goto finish;
21553a5a1b3Sopenharmony_ci        }
21653a5a1b3Sopenharmony_ci        if (!dbus_connection_send(conn, reply, NULL)) {
21753a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NEED_MEMORY;
21853a5a1b3Sopenharmony_ci            goto finish;
21953a5a1b3Sopenharmony_ci        }
22053a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_HANDLED;
22153a5a1b3Sopenharmony_ci        goto finish;
22253a5a1b3Sopenharmony_ci    }
22353a5a1b3Sopenharmony_ci
22453a5a1b3Sopenharmony_ci    if (*interface && !pa_streq(interface, INTERFACE)) {
22553a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
22653a5a1b3Sopenharmony_ci        goto finish;
22753a5a1b3Sopenharmony_ci    }
22853a5a1b3Sopenharmony_ci
22953a5a1b3Sopenharmony_ci    if (!pa_streq(property, "Address")) {
23053a5a1b3Sopenharmony_ci        if (!(reply = dbus_message_new_error_printf(msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s: No such property", property))) {
23153a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
23253a5a1b3Sopenharmony_ci            goto finish;
23353a5a1b3Sopenharmony_ci        }
23453a5a1b3Sopenharmony_ci        if (!dbus_connection_send(conn, reply, NULL)) {
23553a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NEED_MEMORY;
23653a5a1b3Sopenharmony_ci            goto finish;
23753a5a1b3Sopenharmony_ci        }
23853a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_HANDLED;
23953a5a1b3Sopenharmony_ci        goto finish;
24053a5a1b3Sopenharmony_ci    }
24153a5a1b3Sopenharmony_ci
24253a5a1b3Sopenharmony_ci    r = handle_get_address(conn, msg, sl);
24353a5a1b3Sopenharmony_ci
24453a5a1b3Sopenharmony_cifinish:
24553a5a1b3Sopenharmony_ci    if (reply)
24653a5a1b3Sopenharmony_ci        dbus_message_unref(reply);
24753a5a1b3Sopenharmony_ci
24853a5a1b3Sopenharmony_ci    return r;
24953a5a1b3Sopenharmony_ci}
25053a5a1b3Sopenharmony_ci
25153a5a1b3Sopenharmony_cistatic DBusHandlerResult handle_set(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) {
25253a5a1b3Sopenharmony_ci    DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
25353a5a1b3Sopenharmony_ci    const char* interface;
25453a5a1b3Sopenharmony_ci    const char* property;
25553a5a1b3Sopenharmony_ci    DBusMessage *reply = NULL;
25653a5a1b3Sopenharmony_ci
25753a5a1b3Sopenharmony_ci    pa_assert(conn);
25853a5a1b3Sopenharmony_ci    pa_assert(msg);
25953a5a1b3Sopenharmony_ci    pa_assert(sl);
26053a5a1b3Sopenharmony_ci
26153a5a1b3Sopenharmony_ci    if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
26253a5a1b3Sopenharmony_ci        if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) {
26353a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
26453a5a1b3Sopenharmony_ci            goto finish;
26553a5a1b3Sopenharmony_ci        }
26653a5a1b3Sopenharmony_ci        if (!dbus_connection_send(conn, reply, NULL)) {
26753a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NEED_MEMORY;
26853a5a1b3Sopenharmony_ci            goto finish;
26953a5a1b3Sopenharmony_ci        }
27053a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_HANDLED;
27153a5a1b3Sopenharmony_ci        goto finish;
27253a5a1b3Sopenharmony_ci    }
27353a5a1b3Sopenharmony_ci
27453a5a1b3Sopenharmony_ci    if (*interface && !pa_streq(interface, INTERFACE)) {
27553a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
27653a5a1b3Sopenharmony_ci        goto finish;
27753a5a1b3Sopenharmony_ci    }
27853a5a1b3Sopenharmony_ci
27953a5a1b3Sopenharmony_ci    if (!pa_streq(property, "Address")) {
28053a5a1b3Sopenharmony_ci        if (!(reply = dbus_message_new_error_printf(msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s: No such property", property))) {
28153a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
28253a5a1b3Sopenharmony_ci            goto finish;
28353a5a1b3Sopenharmony_ci        }
28453a5a1b3Sopenharmony_ci        if (!dbus_connection_send(conn, reply, NULL)) {
28553a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NEED_MEMORY;
28653a5a1b3Sopenharmony_ci            goto finish;
28753a5a1b3Sopenharmony_ci        }
28853a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_HANDLED;
28953a5a1b3Sopenharmony_ci        goto finish;
29053a5a1b3Sopenharmony_ci    }
29153a5a1b3Sopenharmony_ci
29253a5a1b3Sopenharmony_ci    if (!(reply = dbus_message_new_error_printf(msg, DBUS_ERROR_ACCESS_DENIED, "%s: Property not settable", property))) {
29353a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
29453a5a1b3Sopenharmony_ci        goto finish;
29553a5a1b3Sopenharmony_ci    }
29653a5a1b3Sopenharmony_ci    if (!dbus_connection_send(conn, reply, NULL)) {
29753a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_NEED_MEMORY;
29853a5a1b3Sopenharmony_ci        goto finish;
29953a5a1b3Sopenharmony_ci    }
30053a5a1b3Sopenharmony_ci    r = DBUS_HANDLER_RESULT_HANDLED;
30153a5a1b3Sopenharmony_ci
30253a5a1b3Sopenharmony_cifinish:
30353a5a1b3Sopenharmony_ci    if (reply)
30453a5a1b3Sopenharmony_ci        dbus_message_unref(reply);
30553a5a1b3Sopenharmony_ci
30653a5a1b3Sopenharmony_ci    return r;
30753a5a1b3Sopenharmony_ci}
30853a5a1b3Sopenharmony_ci
30953a5a1b3Sopenharmony_cistatic DBusHandlerResult handle_get_all(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) {
31053a5a1b3Sopenharmony_ci    DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
31153a5a1b3Sopenharmony_ci    DBusMessage *reply = NULL;
31253a5a1b3Sopenharmony_ci    const char *property = "Address";
31353a5a1b3Sopenharmony_ci    char *interface = NULL;
31453a5a1b3Sopenharmony_ci    char *address = NULL;
31553a5a1b3Sopenharmony_ci    DBusMessageIter msg_iter;
31653a5a1b3Sopenharmony_ci    DBusMessageIter dict_iter;
31753a5a1b3Sopenharmony_ci    DBusMessageIter dict_entry_iter;
31853a5a1b3Sopenharmony_ci    DBusMessageIter variant_iter;
31953a5a1b3Sopenharmony_ci
32053a5a1b3Sopenharmony_ci    pa_assert(conn);
32153a5a1b3Sopenharmony_ci    pa_assert(msg);
32253a5a1b3Sopenharmony_ci    pa_assert(sl);
32353a5a1b3Sopenharmony_ci
32453a5a1b3Sopenharmony_ci    if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_INVALID)) {
32553a5a1b3Sopenharmony_ci        if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) {
32653a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
32753a5a1b3Sopenharmony_ci            goto finish;
32853a5a1b3Sopenharmony_ci        }
32953a5a1b3Sopenharmony_ci        if (!dbus_connection_send(conn, reply, NULL)) {
33053a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_NEED_MEMORY;
33153a5a1b3Sopenharmony_ci            goto finish;
33253a5a1b3Sopenharmony_ci        }
33353a5a1b3Sopenharmony_ci        r = DBUS_HANDLER_RESULT_HANDLED;
33453a5a1b3Sopenharmony_ci        goto finish;
33553a5a1b3Sopenharmony_ci    }
33653a5a1b3Sopenharmony_ci
33753a5a1b3Sopenharmony_ci    switch (get_address(sl->core->server_type, &address)) {
33853a5a1b3Sopenharmony_ci        case SUCCESS:
33953a5a1b3Sopenharmony_ci            if (!(reply = dbus_message_new_method_return(msg))) {
34053a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
34153a5a1b3Sopenharmony_ci                goto finish;
34253a5a1b3Sopenharmony_ci            }
34353a5a1b3Sopenharmony_ci            dbus_message_iter_init_append(reply, &msg_iter);
34453a5a1b3Sopenharmony_ci            if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)) {
34553a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
34653a5a1b3Sopenharmony_ci                goto finish;
34753a5a1b3Sopenharmony_ci            }
34853a5a1b3Sopenharmony_ci            if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)) {
34953a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
35053a5a1b3Sopenharmony_ci                goto finish;
35153a5a1b3Sopenharmony_ci            }
35253a5a1b3Sopenharmony_ci            if (!dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &property)) {
35353a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
35453a5a1b3Sopenharmony_ci                goto finish;
35553a5a1b3Sopenharmony_ci            }
35653a5a1b3Sopenharmony_ci            if (!dbus_message_iter_open_container(&dict_entry_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) {
35753a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
35853a5a1b3Sopenharmony_ci                goto finish;
35953a5a1b3Sopenharmony_ci            }
36053a5a1b3Sopenharmony_ci            if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &address)) {
36153a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
36253a5a1b3Sopenharmony_ci                goto finish;
36353a5a1b3Sopenharmony_ci            }
36453a5a1b3Sopenharmony_ci            if (!dbus_message_iter_close_container(&dict_entry_iter, &variant_iter)) {
36553a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
36653a5a1b3Sopenharmony_ci                goto finish;
36753a5a1b3Sopenharmony_ci            }
36853a5a1b3Sopenharmony_ci            if (!dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)) {
36953a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
37053a5a1b3Sopenharmony_ci                goto finish;
37153a5a1b3Sopenharmony_ci            }
37253a5a1b3Sopenharmony_ci            if (!dbus_message_iter_close_container(&msg_iter, &dict_iter)) {
37353a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
37453a5a1b3Sopenharmony_ci                goto finish;
37553a5a1b3Sopenharmony_ci            }
37653a5a1b3Sopenharmony_ci            if (!dbus_connection_send(conn, reply, NULL)) {
37753a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
37853a5a1b3Sopenharmony_ci                goto finish;
37953a5a1b3Sopenharmony_ci            }
38053a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_HANDLED;
38153a5a1b3Sopenharmony_ci            goto finish;
38253a5a1b3Sopenharmony_ci
38353a5a1b3Sopenharmony_ci        case SERVER_FROM_TYPE_FAILED:
38453a5a1b3Sopenharmony_ci            if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) {
38553a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
38653a5a1b3Sopenharmony_ci                goto finish;
38753a5a1b3Sopenharmony_ci            }
38853a5a1b3Sopenharmony_ci            if (!dbus_connection_send(conn, reply, NULL)) {
38953a5a1b3Sopenharmony_ci                r = DBUS_HANDLER_RESULT_NEED_MEMORY;
39053a5a1b3Sopenharmony_ci                goto finish;
39153a5a1b3Sopenharmony_ci            }
39253a5a1b3Sopenharmony_ci            r = DBUS_HANDLER_RESULT_HANDLED;
39353a5a1b3Sopenharmony_ci            goto finish;
39453a5a1b3Sopenharmony_ci
39553a5a1b3Sopenharmony_ci        default:
39653a5a1b3Sopenharmony_ci            pa_assert_not_reached();
39753a5a1b3Sopenharmony_ci    }
39853a5a1b3Sopenharmony_ci
39953a5a1b3Sopenharmony_cifinish:
40053a5a1b3Sopenharmony_ci    pa_xfree(address);
40153a5a1b3Sopenharmony_ci    if (reply)
40253a5a1b3Sopenharmony_ci        dbus_message_unref(reply);
40353a5a1b3Sopenharmony_ci
40453a5a1b3Sopenharmony_ci    return r;
40553a5a1b3Sopenharmony_ci}
40653a5a1b3Sopenharmony_ci
40753a5a1b3Sopenharmony_cistatic DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void *user_data) {
40853a5a1b3Sopenharmony_ci    pa_dbusobj_server_lookup *sl = user_data;
40953a5a1b3Sopenharmony_ci
41053a5a1b3Sopenharmony_ci    pa_assert(conn);
41153a5a1b3Sopenharmony_ci    pa_assert(msg);
41253a5a1b3Sopenharmony_ci    pa_assert(sl);
41353a5a1b3Sopenharmony_ci
41453a5a1b3Sopenharmony_ci    /* pa_log("Got message! type = %s   path = %s   iface = %s   member = %s   dest = %s", dbus_message_type_to_string(dbus_message_get_type(msg)), dbus_message_get_path(msg), dbus_message_get_interface(msg), dbus_message_get_member(msg), dbus_message_get_destination(msg)); */
41553a5a1b3Sopenharmony_ci
41653a5a1b3Sopenharmony_ci    if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL)
41753a5a1b3Sopenharmony_ci        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
41853a5a1b3Sopenharmony_ci
41953a5a1b3Sopenharmony_ci    if (dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE, "Introspect") ||
42053a5a1b3Sopenharmony_ci        (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Introspect")))
42153a5a1b3Sopenharmony_ci        return handle_introspect(conn, msg, sl);
42253a5a1b3Sopenharmony_ci
42353a5a1b3Sopenharmony_ci    if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Get") ||
42453a5a1b3Sopenharmony_ci        (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Get")))
42553a5a1b3Sopenharmony_ci        return handle_get(conn, msg, sl);
42653a5a1b3Sopenharmony_ci
42753a5a1b3Sopenharmony_ci    if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Set") ||
42853a5a1b3Sopenharmony_ci        (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Set")))
42953a5a1b3Sopenharmony_ci        return handle_set(conn, msg, sl);
43053a5a1b3Sopenharmony_ci
43153a5a1b3Sopenharmony_ci    if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "GetAll") ||
43253a5a1b3Sopenharmony_ci        (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "GetAll")))
43353a5a1b3Sopenharmony_ci        return handle_get_all(conn, msg, sl);
43453a5a1b3Sopenharmony_ci
43553a5a1b3Sopenharmony_ci    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
43653a5a1b3Sopenharmony_ci}
43753a5a1b3Sopenharmony_ci
43853a5a1b3Sopenharmony_cistatic DBusObjectPathVTable vtable = {
43953a5a1b3Sopenharmony_ci    .unregister_function = unregister_cb,
44053a5a1b3Sopenharmony_ci    .message_function = message_cb,
44153a5a1b3Sopenharmony_ci    .dbus_internal_pad1 = NULL,
44253a5a1b3Sopenharmony_ci    .dbus_internal_pad2 = NULL,
44353a5a1b3Sopenharmony_ci    .dbus_internal_pad3 = NULL,
44453a5a1b3Sopenharmony_ci    .dbus_internal_pad4 = NULL
44553a5a1b3Sopenharmony_ci};
44653a5a1b3Sopenharmony_ci
44753a5a1b3Sopenharmony_cipa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c) {
44853a5a1b3Sopenharmony_ci    pa_dbusobj_server_lookup *sl;
44953a5a1b3Sopenharmony_ci    DBusError error;
45053a5a1b3Sopenharmony_ci
45153a5a1b3Sopenharmony_ci    dbus_error_init(&error);
45253a5a1b3Sopenharmony_ci
45353a5a1b3Sopenharmony_ci    sl = pa_xnew(pa_dbusobj_server_lookup, 1);
45453a5a1b3Sopenharmony_ci    sl->core = c;
45553a5a1b3Sopenharmony_ci    sl->path_registered = false;
45653a5a1b3Sopenharmony_ci
45753a5a1b3Sopenharmony_ci    if (!(sl->conn = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
45853a5a1b3Sopenharmony_ci        pa_log_warn("Unable to contact D-Bus: %s: %s", error.name, error.message);
45953a5a1b3Sopenharmony_ci        goto fail;
46053a5a1b3Sopenharmony_ci    }
46153a5a1b3Sopenharmony_ci
46253a5a1b3Sopenharmony_ci    if (!dbus_connection_register_object_path(pa_dbus_connection_get(sl->conn), OBJECT_PATH, &vtable, sl)) {
46353a5a1b3Sopenharmony_ci        pa_log("dbus_connection_register_object_path() failed for " OBJECT_PATH ".");
46453a5a1b3Sopenharmony_ci        goto fail;
46553a5a1b3Sopenharmony_ci    }
46653a5a1b3Sopenharmony_ci
46753a5a1b3Sopenharmony_ci    sl->path_registered = true;
46853a5a1b3Sopenharmony_ci
46953a5a1b3Sopenharmony_ci    return sl;
47053a5a1b3Sopenharmony_ci
47153a5a1b3Sopenharmony_cifail:
47253a5a1b3Sopenharmony_ci    dbus_error_free(&error);
47353a5a1b3Sopenharmony_ci
47453a5a1b3Sopenharmony_ci    pa_dbusobj_server_lookup_free(sl);
47553a5a1b3Sopenharmony_ci
47653a5a1b3Sopenharmony_ci    return NULL;
47753a5a1b3Sopenharmony_ci}
47853a5a1b3Sopenharmony_ci
47953a5a1b3Sopenharmony_civoid pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl) {
48053a5a1b3Sopenharmony_ci    pa_assert(sl);
48153a5a1b3Sopenharmony_ci
48253a5a1b3Sopenharmony_ci    if (sl->path_registered) {
48353a5a1b3Sopenharmony_ci        pa_assert(sl->conn);
48453a5a1b3Sopenharmony_ci        if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(sl->conn), OBJECT_PATH))
48553a5a1b3Sopenharmony_ci            pa_log_debug("dbus_connection_unregister_object_path() failed for " OBJECT_PATH ".");
48653a5a1b3Sopenharmony_ci    }
48753a5a1b3Sopenharmony_ci
48853a5a1b3Sopenharmony_ci    if (sl->conn)
48953a5a1b3Sopenharmony_ci        pa_dbus_connection_unref(sl->conn);
49053a5a1b3Sopenharmony_ci
49153a5a1b3Sopenharmony_ci    pa_xfree(sl);
49253a5a1b3Sopenharmony_ci}
493