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