153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2006 Lennart Poettering 553a5a1b3Sopenharmony_ci Copyright 2006 Shams E. King 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 953a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 1053a5a1b3Sopenharmony_ci or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1853a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <stdarg.h> 2653a5a1b3Sopenharmony_ci 2753a5a1b3Sopenharmony_ci#include <pulse/rtclock.h> 2853a5a1b3Sopenharmony_ci#include <pulse/timeval.h> 2953a5a1b3Sopenharmony_ci#include <pulse/utf8.h> 3053a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h> 3153a5a1b3Sopenharmony_ci 3253a5a1b3Sopenharmony_ci#include <pulsecore/core-rtclock.h> 3353a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 3453a5a1b3Sopenharmony_ci#include <pulsecore/log.h> 3553a5a1b3Sopenharmony_ci 3653a5a1b3Sopenharmony_ci#include "dbus-util.h" 3753a5a1b3Sopenharmony_ci 3853a5a1b3Sopenharmony_cistruct pa_dbus_wrap_connection { 3953a5a1b3Sopenharmony_ci pa_mainloop_api *mainloop; 4053a5a1b3Sopenharmony_ci DBusConnection *connection; 4153a5a1b3Sopenharmony_ci pa_defer_event* dispatch_event; 4253a5a1b3Sopenharmony_ci bool use_rtclock:1; 4353a5a1b3Sopenharmony_ci}; 4453a5a1b3Sopenharmony_ci 4553a5a1b3Sopenharmony_cistruct timeout_data { 4653a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *connection; 4753a5a1b3Sopenharmony_ci DBusTimeout *timeout; 4853a5a1b3Sopenharmony_ci}; 4953a5a1b3Sopenharmony_ci 5053a5a1b3Sopenharmony_cistatic void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) { 5153a5a1b3Sopenharmony_ci DBusConnection *conn = userdata; 5253a5a1b3Sopenharmony_ci 5353a5a1b3Sopenharmony_ci if (dbus_connection_dispatch(conn) == DBUS_DISPATCH_COMPLETE) 5453a5a1b3Sopenharmony_ci /* no more data to process, disable the deferred */ 5553a5a1b3Sopenharmony_ci ea->defer_enable(ev, 0); 5653a5a1b3Sopenharmony_ci} 5753a5a1b3Sopenharmony_ci 5853a5a1b3Sopenharmony_ci/* DBusDispatchStatusFunction callback for the pa mainloop */ 5953a5a1b3Sopenharmony_cistatic void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, void *userdata) { 6053a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *c = userdata; 6153a5a1b3Sopenharmony_ci 6253a5a1b3Sopenharmony_ci pa_assert(c); 6353a5a1b3Sopenharmony_ci 6453a5a1b3Sopenharmony_ci switch(status) { 6553a5a1b3Sopenharmony_ci 6653a5a1b3Sopenharmony_ci case DBUS_DISPATCH_COMPLETE: 6753a5a1b3Sopenharmony_ci c->mainloop->defer_enable(c->dispatch_event, 0); 6853a5a1b3Sopenharmony_ci break; 6953a5a1b3Sopenharmony_ci 7053a5a1b3Sopenharmony_ci case DBUS_DISPATCH_DATA_REMAINS: 7153a5a1b3Sopenharmony_ci case DBUS_DISPATCH_NEED_MEMORY: 7253a5a1b3Sopenharmony_ci default: 7353a5a1b3Sopenharmony_ci c->mainloop->defer_enable(c->dispatch_event, 1); 7453a5a1b3Sopenharmony_ci break; 7553a5a1b3Sopenharmony_ci } 7653a5a1b3Sopenharmony_ci} 7753a5a1b3Sopenharmony_ci 7853a5a1b3Sopenharmony_cistatic pa_io_event_flags_t get_watch_flags(DBusWatch *watch) { 7953a5a1b3Sopenharmony_ci unsigned int flags; 8053a5a1b3Sopenharmony_ci pa_io_event_flags_t events = 0; 8153a5a1b3Sopenharmony_ci 8253a5a1b3Sopenharmony_ci pa_assert(watch); 8353a5a1b3Sopenharmony_ci 8453a5a1b3Sopenharmony_ci flags = dbus_watch_get_flags(watch); 8553a5a1b3Sopenharmony_ci 8653a5a1b3Sopenharmony_ci /* no watch flags for disabled watches */ 8753a5a1b3Sopenharmony_ci if (!dbus_watch_get_enabled(watch)) 8853a5a1b3Sopenharmony_ci return PA_IO_EVENT_NULL; 8953a5a1b3Sopenharmony_ci 9053a5a1b3Sopenharmony_ci if (flags & DBUS_WATCH_READABLE) 9153a5a1b3Sopenharmony_ci events |= PA_IO_EVENT_INPUT; 9253a5a1b3Sopenharmony_ci if (flags & DBUS_WATCH_WRITABLE) 9353a5a1b3Sopenharmony_ci events |= PA_IO_EVENT_OUTPUT; 9453a5a1b3Sopenharmony_ci 9553a5a1b3Sopenharmony_ci return events | PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR; 9653a5a1b3Sopenharmony_ci} 9753a5a1b3Sopenharmony_ci 9853a5a1b3Sopenharmony_ci/* pa_io_event_cb_t IO event handler */ 9953a5a1b3Sopenharmony_cistatic void handle_io_event(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) { 10053a5a1b3Sopenharmony_ci unsigned int flags = 0; 10153a5a1b3Sopenharmony_ci DBusWatch *watch = userdata; 10253a5a1b3Sopenharmony_ci 10353a5a1b3Sopenharmony_ci pa_assert(fd == dbus_watch_get_unix_fd(watch)); 10453a5a1b3Sopenharmony_ci 10553a5a1b3Sopenharmony_ci if (!dbus_watch_get_enabled(watch)) { 10653a5a1b3Sopenharmony_ci pa_log_warn("Asked to handle disabled watch: %p %i", (void*) watch, fd); 10753a5a1b3Sopenharmony_ci return; 10853a5a1b3Sopenharmony_ci } 10953a5a1b3Sopenharmony_ci 11053a5a1b3Sopenharmony_ci if (events & PA_IO_EVENT_INPUT) 11153a5a1b3Sopenharmony_ci flags |= DBUS_WATCH_READABLE; 11253a5a1b3Sopenharmony_ci if (events & PA_IO_EVENT_OUTPUT) 11353a5a1b3Sopenharmony_ci flags |= DBUS_WATCH_WRITABLE; 11453a5a1b3Sopenharmony_ci if (events & PA_IO_EVENT_HANGUP) 11553a5a1b3Sopenharmony_ci flags |= DBUS_WATCH_HANGUP; 11653a5a1b3Sopenharmony_ci if (events & PA_IO_EVENT_ERROR) 11753a5a1b3Sopenharmony_ci flags |= DBUS_WATCH_ERROR; 11853a5a1b3Sopenharmony_ci 11953a5a1b3Sopenharmony_ci dbus_watch_handle(watch, flags); 12053a5a1b3Sopenharmony_ci} 12153a5a1b3Sopenharmony_ci 12253a5a1b3Sopenharmony_ci/* pa_time_event_cb_t timer event handler */ 12353a5a1b3Sopenharmony_cistatic void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *t, void *userdata) { 12453a5a1b3Sopenharmony_ci struct timeval tv; 12553a5a1b3Sopenharmony_ci struct timeout_data *d = userdata; 12653a5a1b3Sopenharmony_ci 12753a5a1b3Sopenharmony_ci pa_assert(d); 12853a5a1b3Sopenharmony_ci pa_assert(d->connection); 12953a5a1b3Sopenharmony_ci 13053a5a1b3Sopenharmony_ci if (dbus_timeout_get_enabled(d->timeout)) { 13153a5a1b3Sopenharmony_ci /* Restart it for the next scheduled time. We do this before 13253a5a1b3Sopenharmony_ci * calling dbus_timeout_handle() to make sure that the time 13353a5a1b3Sopenharmony_ci * event is still around. */ 13453a5a1b3Sopenharmony_ci ea->time_restart(e, pa_timeval_rtstore(&tv, 13553a5a1b3Sopenharmony_ci pa_timeval_load(t) + dbus_timeout_get_interval(d->timeout) * PA_USEC_PER_MSEC, 13653a5a1b3Sopenharmony_ci d->connection->use_rtclock)); 13753a5a1b3Sopenharmony_ci 13853a5a1b3Sopenharmony_ci dbus_timeout_handle(d->timeout); 13953a5a1b3Sopenharmony_ci } 14053a5a1b3Sopenharmony_ci} 14153a5a1b3Sopenharmony_ci 14253a5a1b3Sopenharmony_ci/* DBusAddWatchFunction callback for pa mainloop */ 14353a5a1b3Sopenharmony_cistatic dbus_bool_t add_watch(DBusWatch *watch, void *data) { 14453a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *c = data; 14553a5a1b3Sopenharmony_ci pa_io_event *ev; 14653a5a1b3Sopenharmony_ci 14753a5a1b3Sopenharmony_ci pa_assert(watch); 14853a5a1b3Sopenharmony_ci pa_assert(c); 14953a5a1b3Sopenharmony_ci 15053a5a1b3Sopenharmony_ci ev = c->mainloop->io_new( 15153a5a1b3Sopenharmony_ci c->mainloop, 15253a5a1b3Sopenharmony_ci dbus_watch_get_unix_fd(watch), 15353a5a1b3Sopenharmony_ci get_watch_flags(watch), handle_io_event, watch); 15453a5a1b3Sopenharmony_ci 15553a5a1b3Sopenharmony_ci dbus_watch_set_data(watch, ev, NULL); 15653a5a1b3Sopenharmony_ci 15753a5a1b3Sopenharmony_ci return TRUE; 15853a5a1b3Sopenharmony_ci} 15953a5a1b3Sopenharmony_ci 16053a5a1b3Sopenharmony_ci/* DBusRemoveWatchFunction callback for pa mainloop */ 16153a5a1b3Sopenharmony_cistatic void remove_watch(DBusWatch *watch, void *data) { 16253a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *c = data; 16353a5a1b3Sopenharmony_ci pa_io_event *ev; 16453a5a1b3Sopenharmony_ci 16553a5a1b3Sopenharmony_ci pa_assert(watch); 16653a5a1b3Sopenharmony_ci pa_assert(c); 16753a5a1b3Sopenharmony_ci 16853a5a1b3Sopenharmony_ci if ((ev = dbus_watch_get_data(watch))) 16953a5a1b3Sopenharmony_ci c->mainloop->io_free(ev); 17053a5a1b3Sopenharmony_ci} 17153a5a1b3Sopenharmony_ci 17253a5a1b3Sopenharmony_ci/* DBusWatchToggledFunction callback for pa mainloop */ 17353a5a1b3Sopenharmony_cistatic void toggle_watch(DBusWatch *watch, void *data) { 17453a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *c = data; 17553a5a1b3Sopenharmony_ci pa_io_event *ev; 17653a5a1b3Sopenharmony_ci 17753a5a1b3Sopenharmony_ci pa_assert(watch); 17853a5a1b3Sopenharmony_ci pa_assert(c); 17953a5a1b3Sopenharmony_ci 18053a5a1b3Sopenharmony_ci pa_assert_se(ev = dbus_watch_get_data(watch)); 18153a5a1b3Sopenharmony_ci 18253a5a1b3Sopenharmony_ci /* get_watch_flags() checks if the watch is enabled */ 18353a5a1b3Sopenharmony_ci c->mainloop->io_enable(ev, get_watch_flags(watch)); 18453a5a1b3Sopenharmony_ci} 18553a5a1b3Sopenharmony_ci 18653a5a1b3Sopenharmony_cistatic void time_event_destroy_cb(pa_mainloop_api *a, pa_time_event *e, void *userdata) { 18753a5a1b3Sopenharmony_ci pa_xfree(userdata); 18853a5a1b3Sopenharmony_ci} 18953a5a1b3Sopenharmony_ci 19053a5a1b3Sopenharmony_ci/* DBusAddTimeoutFunction callback for pa mainloop */ 19153a5a1b3Sopenharmony_cistatic dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { 19253a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *c = data; 19353a5a1b3Sopenharmony_ci pa_time_event *ev; 19453a5a1b3Sopenharmony_ci struct timeval tv; 19553a5a1b3Sopenharmony_ci struct timeout_data *d; 19653a5a1b3Sopenharmony_ci 19753a5a1b3Sopenharmony_ci pa_assert(timeout); 19853a5a1b3Sopenharmony_ci pa_assert(c); 19953a5a1b3Sopenharmony_ci 20053a5a1b3Sopenharmony_ci if (!dbus_timeout_get_enabled(timeout)) 20153a5a1b3Sopenharmony_ci return FALSE; 20253a5a1b3Sopenharmony_ci 20353a5a1b3Sopenharmony_ci d = pa_xnew(struct timeout_data, 1); 20453a5a1b3Sopenharmony_ci d->connection = c; 20553a5a1b3Sopenharmony_ci d->timeout = timeout; 20653a5a1b3Sopenharmony_ci ev = c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + dbus_timeout_get_interval(timeout) * PA_USEC_PER_MSEC, c->use_rtclock), handle_time_event, d); 20753a5a1b3Sopenharmony_ci c->mainloop->time_set_destroy(ev, time_event_destroy_cb); 20853a5a1b3Sopenharmony_ci 20953a5a1b3Sopenharmony_ci dbus_timeout_set_data(timeout, ev, NULL); 21053a5a1b3Sopenharmony_ci 21153a5a1b3Sopenharmony_ci return TRUE; 21253a5a1b3Sopenharmony_ci} 21353a5a1b3Sopenharmony_ci 21453a5a1b3Sopenharmony_ci/* DBusRemoveTimeoutFunction callback for pa mainloop */ 21553a5a1b3Sopenharmony_cistatic void remove_timeout(DBusTimeout *timeout, void *data) { 21653a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *c = data; 21753a5a1b3Sopenharmony_ci pa_time_event *ev; 21853a5a1b3Sopenharmony_ci 21953a5a1b3Sopenharmony_ci pa_assert(timeout); 22053a5a1b3Sopenharmony_ci pa_assert(c); 22153a5a1b3Sopenharmony_ci 22253a5a1b3Sopenharmony_ci if ((ev = dbus_timeout_get_data(timeout))) 22353a5a1b3Sopenharmony_ci c->mainloop->time_free(ev); 22453a5a1b3Sopenharmony_ci} 22553a5a1b3Sopenharmony_ci 22653a5a1b3Sopenharmony_ci/* DBusTimeoutToggledFunction callback for pa mainloop */ 22753a5a1b3Sopenharmony_cistatic void toggle_timeout(DBusTimeout *timeout, void *data) { 22853a5a1b3Sopenharmony_ci struct timeout_data *d = data; 22953a5a1b3Sopenharmony_ci pa_time_event *ev; 23053a5a1b3Sopenharmony_ci struct timeval tv; 23153a5a1b3Sopenharmony_ci 23253a5a1b3Sopenharmony_ci pa_assert(d); 23353a5a1b3Sopenharmony_ci pa_assert(d->connection); 23453a5a1b3Sopenharmony_ci pa_assert(timeout); 23553a5a1b3Sopenharmony_ci 23653a5a1b3Sopenharmony_ci pa_assert_se(ev = dbus_timeout_get_data(timeout)); 23753a5a1b3Sopenharmony_ci 23853a5a1b3Sopenharmony_ci if (dbus_timeout_get_enabled(timeout)) 23953a5a1b3Sopenharmony_ci d->connection->mainloop->time_restart(ev, pa_timeval_rtstore(&tv, pa_rtclock_now() + dbus_timeout_get_interval(timeout) * PA_USEC_PER_MSEC, d->connection->use_rtclock)); 24053a5a1b3Sopenharmony_ci else 24153a5a1b3Sopenharmony_ci d->connection->mainloop->time_restart(ev, pa_timeval_rtstore(&tv, PA_USEC_INVALID, d->connection->use_rtclock)); 24253a5a1b3Sopenharmony_ci} 24353a5a1b3Sopenharmony_ci 24453a5a1b3Sopenharmony_cistatic void wakeup_main(void *userdata) { 24553a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *c = userdata; 24653a5a1b3Sopenharmony_ci 24753a5a1b3Sopenharmony_ci pa_assert(c); 24853a5a1b3Sopenharmony_ci 24953a5a1b3Sopenharmony_ci /* this will wakeup the mainloop and dispatch events, although 25053a5a1b3Sopenharmony_ci * it may not be the cleanest way of accomplishing it */ 25153a5a1b3Sopenharmony_ci c->mainloop->defer_enable(c->dispatch_event, 1); 25253a5a1b3Sopenharmony_ci} 25353a5a1b3Sopenharmony_ci 25453a5a1b3Sopenharmony_cipa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, bool use_rtclock, DBusBusType type, DBusError *error) { 25553a5a1b3Sopenharmony_ci DBusConnection *conn; 25653a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *pconn; 25753a5a1b3Sopenharmony_ci char *id; 25853a5a1b3Sopenharmony_ci 25953a5a1b3Sopenharmony_ci pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER); 26053a5a1b3Sopenharmony_ci 26153a5a1b3Sopenharmony_ci if (!(conn = dbus_bus_get_private(type, error))) 26253a5a1b3Sopenharmony_ci return NULL; 26353a5a1b3Sopenharmony_ci 26453a5a1b3Sopenharmony_ci pconn = pa_xnew(pa_dbus_wrap_connection, 1); 26553a5a1b3Sopenharmony_ci pconn->mainloop = m; 26653a5a1b3Sopenharmony_ci pconn->connection = conn; 26753a5a1b3Sopenharmony_ci pconn->use_rtclock = use_rtclock; 26853a5a1b3Sopenharmony_ci 26953a5a1b3Sopenharmony_ci dbus_connection_set_exit_on_disconnect(conn, FALSE); 27053a5a1b3Sopenharmony_ci dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL); 27153a5a1b3Sopenharmony_ci dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, pconn, NULL); 27253a5a1b3Sopenharmony_ci dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, pconn, NULL); 27353a5a1b3Sopenharmony_ci dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL); 27453a5a1b3Sopenharmony_ci 27553a5a1b3Sopenharmony_ci pconn->dispatch_event = pconn->mainloop->defer_new(pconn->mainloop, dispatch_cb, conn); 27653a5a1b3Sopenharmony_ci 27753a5a1b3Sopenharmony_ci pa_log_debug("Successfully connected to D-Bus %s bus %s as %s", 27853a5a1b3Sopenharmony_ci type == DBUS_BUS_SYSTEM ? "system" : (type == DBUS_BUS_SESSION ? "session" : "starter"), 27953a5a1b3Sopenharmony_ci pa_strnull((id = dbus_connection_get_server_id(conn))), 28053a5a1b3Sopenharmony_ci pa_strnull(dbus_bus_get_unique_name(conn))); 28153a5a1b3Sopenharmony_ci 28253a5a1b3Sopenharmony_ci dbus_free(id); 28353a5a1b3Sopenharmony_ci 28453a5a1b3Sopenharmony_ci return pconn; 28553a5a1b3Sopenharmony_ci} 28653a5a1b3Sopenharmony_ci 28753a5a1b3Sopenharmony_cipa_dbus_wrap_connection* pa_dbus_wrap_connection_new_from_existing( 28853a5a1b3Sopenharmony_ci pa_mainloop_api *m, 28953a5a1b3Sopenharmony_ci bool use_rtclock, 29053a5a1b3Sopenharmony_ci DBusConnection *conn) { 29153a5a1b3Sopenharmony_ci pa_dbus_wrap_connection *pconn; 29253a5a1b3Sopenharmony_ci 29353a5a1b3Sopenharmony_ci pa_assert(m); 29453a5a1b3Sopenharmony_ci pa_assert(conn); 29553a5a1b3Sopenharmony_ci 29653a5a1b3Sopenharmony_ci pconn = pa_xnew(pa_dbus_wrap_connection, 1); 29753a5a1b3Sopenharmony_ci pconn->mainloop = m; 29853a5a1b3Sopenharmony_ci pconn->connection = dbus_connection_ref(conn); 29953a5a1b3Sopenharmony_ci pconn->use_rtclock = use_rtclock; 30053a5a1b3Sopenharmony_ci 30153a5a1b3Sopenharmony_ci dbus_connection_set_exit_on_disconnect(conn, FALSE); 30253a5a1b3Sopenharmony_ci dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL); 30353a5a1b3Sopenharmony_ci dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, pconn, NULL); 30453a5a1b3Sopenharmony_ci dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, pconn, NULL); 30553a5a1b3Sopenharmony_ci dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL); 30653a5a1b3Sopenharmony_ci 30753a5a1b3Sopenharmony_ci pconn->dispatch_event = pconn->mainloop->defer_new(pconn->mainloop, dispatch_cb, conn); 30853a5a1b3Sopenharmony_ci 30953a5a1b3Sopenharmony_ci return pconn; 31053a5a1b3Sopenharmony_ci} 31153a5a1b3Sopenharmony_ci 31253a5a1b3Sopenharmony_civoid pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* c) { 31353a5a1b3Sopenharmony_ci pa_assert(c); 31453a5a1b3Sopenharmony_ci 31553a5a1b3Sopenharmony_ci if (dbus_connection_get_is_connected(c->connection)) { 31653a5a1b3Sopenharmony_ci dbus_connection_close(c->connection); 31753a5a1b3Sopenharmony_ci /* must process remaining messages, bit of a kludge to handle 31853a5a1b3Sopenharmony_ci * both unload and shutdown */ 31953a5a1b3Sopenharmony_ci while (dbus_connection_read_write_dispatch(c->connection, -1)) 32053a5a1b3Sopenharmony_ci ; 32153a5a1b3Sopenharmony_ci } 32253a5a1b3Sopenharmony_ci 32353a5a1b3Sopenharmony_ci c->mainloop->defer_free(c->dispatch_event); 32453a5a1b3Sopenharmony_ci dbus_connection_unref(c->connection); 32553a5a1b3Sopenharmony_ci pa_xfree(c); 32653a5a1b3Sopenharmony_ci} 32753a5a1b3Sopenharmony_ci 32853a5a1b3Sopenharmony_ciDBusConnection* pa_dbus_wrap_connection_get(pa_dbus_wrap_connection *c) { 32953a5a1b3Sopenharmony_ci pa_assert(c); 33053a5a1b3Sopenharmony_ci pa_assert(c->connection); 33153a5a1b3Sopenharmony_ci 33253a5a1b3Sopenharmony_ci return c->connection; 33353a5a1b3Sopenharmony_ci} 33453a5a1b3Sopenharmony_ci 33553a5a1b3Sopenharmony_ciint pa_dbus_add_matches(DBusConnection *c, DBusError *error, ...) { 33653a5a1b3Sopenharmony_ci const char *t; 33753a5a1b3Sopenharmony_ci va_list ap; 33853a5a1b3Sopenharmony_ci unsigned k = 0; 33953a5a1b3Sopenharmony_ci 34053a5a1b3Sopenharmony_ci pa_assert(c); 34153a5a1b3Sopenharmony_ci pa_assert(error); 34253a5a1b3Sopenharmony_ci 34353a5a1b3Sopenharmony_ci va_start(ap, error); 34453a5a1b3Sopenharmony_ci while ((t = va_arg(ap, const char*))) { 34553a5a1b3Sopenharmony_ci dbus_bus_add_match(c, t, error); 34653a5a1b3Sopenharmony_ci 34753a5a1b3Sopenharmony_ci if (dbus_error_is_set(error)) 34853a5a1b3Sopenharmony_ci goto fail; 34953a5a1b3Sopenharmony_ci 35053a5a1b3Sopenharmony_ci k++; 35153a5a1b3Sopenharmony_ci } 35253a5a1b3Sopenharmony_ci va_end(ap); 35353a5a1b3Sopenharmony_ci return 0; 35453a5a1b3Sopenharmony_ci 35553a5a1b3Sopenharmony_cifail: 35653a5a1b3Sopenharmony_ci 35753a5a1b3Sopenharmony_ci va_end(ap); 35853a5a1b3Sopenharmony_ci va_start(ap, error); 35953a5a1b3Sopenharmony_ci for (; k > 0; k--) { 36053a5a1b3Sopenharmony_ci pa_assert_se(t = va_arg(ap, const char*)); 36153a5a1b3Sopenharmony_ci dbus_bus_remove_match(c, t, NULL); 36253a5a1b3Sopenharmony_ci } 36353a5a1b3Sopenharmony_ci va_end(ap); 36453a5a1b3Sopenharmony_ci 36553a5a1b3Sopenharmony_ci return -1; 36653a5a1b3Sopenharmony_ci} 36753a5a1b3Sopenharmony_ci 36853a5a1b3Sopenharmony_civoid pa_dbus_remove_matches(DBusConnection *c, ...) { 36953a5a1b3Sopenharmony_ci const char *t; 37053a5a1b3Sopenharmony_ci va_list ap; 37153a5a1b3Sopenharmony_ci 37253a5a1b3Sopenharmony_ci pa_assert(c); 37353a5a1b3Sopenharmony_ci 37453a5a1b3Sopenharmony_ci va_start(ap, c); 37553a5a1b3Sopenharmony_ci while ((t = va_arg(ap, const char*))) 37653a5a1b3Sopenharmony_ci dbus_bus_remove_match(c, t, NULL); 37753a5a1b3Sopenharmony_ci va_end(ap); 37853a5a1b3Sopenharmony_ci} 37953a5a1b3Sopenharmony_ci 38053a5a1b3Sopenharmony_cipa_dbus_pending *pa_dbus_pending_new( 38153a5a1b3Sopenharmony_ci DBusConnection *c, 38253a5a1b3Sopenharmony_ci DBusMessage *m, 38353a5a1b3Sopenharmony_ci DBusPendingCall *pending, 38453a5a1b3Sopenharmony_ci void *context_data, 38553a5a1b3Sopenharmony_ci void *call_data) { 38653a5a1b3Sopenharmony_ci 38753a5a1b3Sopenharmony_ci pa_dbus_pending *p; 38853a5a1b3Sopenharmony_ci 38953a5a1b3Sopenharmony_ci pa_assert(pending); 39053a5a1b3Sopenharmony_ci 39153a5a1b3Sopenharmony_ci p = pa_xnew(pa_dbus_pending, 1); 39253a5a1b3Sopenharmony_ci p->connection = c; 39353a5a1b3Sopenharmony_ci p->message = m; 39453a5a1b3Sopenharmony_ci p->pending = pending; 39553a5a1b3Sopenharmony_ci p->context_data = context_data; 39653a5a1b3Sopenharmony_ci p->call_data = call_data; 39753a5a1b3Sopenharmony_ci 39853a5a1b3Sopenharmony_ci PA_LLIST_INIT(pa_dbus_pending, p); 39953a5a1b3Sopenharmony_ci 40053a5a1b3Sopenharmony_ci return p; 40153a5a1b3Sopenharmony_ci} 40253a5a1b3Sopenharmony_ci 40353a5a1b3Sopenharmony_civoid pa_dbus_pending_free(pa_dbus_pending *p) { 40453a5a1b3Sopenharmony_ci pa_assert(p); 40553a5a1b3Sopenharmony_ci 40653a5a1b3Sopenharmony_ci if (p->pending) { 40753a5a1b3Sopenharmony_ci dbus_pending_call_cancel(p->pending); 40853a5a1b3Sopenharmony_ci dbus_pending_call_unref(p->pending); 40953a5a1b3Sopenharmony_ci } 41053a5a1b3Sopenharmony_ci 41153a5a1b3Sopenharmony_ci if (p->message) 41253a5a1b3Sopenharmony_ci dbus_message_unref(p->message); 41353a5a1b3Sopenharmony_ci 41453a5a1b3Sopenharmony_ci pa_xfree(p); 41553a5a1b3Sopenharmony_ci} 41653a5a1b3Sopenharmony_ci 41753a5a1b3Sopenharmony_civoid pa_dbus_sync_pending_list(pa_dbus_pending **p) { 41853a5a1b3Sopenharmony_ci pa_assert(p); 41953a5a1b3Sopenharmony_ci 42053a5a1b3Sopenharmony_ci while (*p && dbus_connection_read_write_dispatch((*p)->connection, -1)) 42153a5a1b3Sopenharmony_ci ; 42253a5a1b3Sopenharmony_ci} 42353a5a1b3Sopenharmony_ci 42453a5a1b3Sopenharmony_civoid pa_dbus_free_pending_list(pa_dbus_pending **p) { 42553a5a1b3Sopenharmony_ci pa_dbus_pending *i; 42653a5a1b3Sopenharmony_ci 42753a5a1b3Sopenharmony_ci pa_assert(p); 42853a5a1b3Sopenharmony_ci 42953a5a1b3Sopenharmony_ci while ((i = *p)) { 43053a5a1b3Sopenharmony_ci PA_LLIST_REMOVE(pa_dbus_pending, *p, i); 43153a5a1b3Sopenharmony_ci pa_dbus_pending_free(i); 43253a5a1b3Sopenharmony_ci } 43353a5a1b3Sopenharmony_ci} 43453a5a1b3Sopenharmony_ci 43553a5a1b3Sopenharmony_ciconst char *pa_dbus_get_error_message(DBusMessage *m) { 43653a5a1b3Sopenharmony_ci const char *message; 43753a5a1b3Sopenharmony_ci 43853a5a1b3Sopenharmony_ci pa_assert(m); 43953a5a1b3Sopenharmony_ci pa_assert(dbus_message_get_type(m) == DBUS_MESSAGE_TYPE_ERROR); 44053a5a1b3Sopenharmony_ci 44153a5a1b3Sopenharmony_ci if (dbus_message_get_signature(m)[0] != 's') 44253a5a1b3Sopenharmony_ci return "<no explanation>"; 44353a5a1b3Sopenharmony_ci 44453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_get_args(m, NULL, DBUS_TYPE_STRING, &message, DBUS_TYPE_INVALID)); 44553a5a1b3Sopenharmony_ci 44653a5a1b3Sopenharmony_ci return message; 44753a5a1b3Sopenharmony_ci} 44853a5a1b3Sopenharmony_ci 44953a5a1b3Sopenharmony_civoid pa_dbus_send_error(DBusConnection *c, DBusMessage *in_reply_to, const char *name, const char *format, ...) { 45053a5a1b3Sopenharmony_ci va_list ap; 45153a5a1b3Sopenharmony_ci char *message; 45253a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 45353a5a1b3Sopenharmony_ci 45453a5a1b3Sopenharmony_ci pa_assert(c); 45553a5a1b3Sopenharmony_ci pa_assert(in_reply_to); 45653a5a1b3Sopenharmony_ci pa_assert(name); 45753a5a1b3Sopenharmony_ci pa_assert(format); 45853a5a1b3Sopenharmony_ci 45953a5a1b3Sopenharmony_ci va_start(ap, format); 46053a5a1b3Sopenharmony_ci message = pa_vsprintf_malloc(format, ap); 46153a5a1b3Sopenharmony_ci va_end(ap); 46253a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_error(in_reply_to, name, message))); 46353a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(c, reply, NULL)); 46453a5a1b3Sopenharmony_ci 46553a5a1b3Sopenharmony_ci dbus_message_unref(reply); 46653a5a1b3Sopenharmony_ci 46753a5a1b3Sopenharmony_ci pa_xfree(message); 46853a5a1b3Sopenharmony_ci} 46953a5a1b3Sopenharmony_ci 47053a5a1b3Sopenharmony_civoid pa_dbus_send_empty_reply(DBusConnection *c, DBusMessage *in_reply_to) { 47153a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 47253a5a1b3Sopenharmony_ci 47353a5a1b3Sopenharmony_ci pa_assert(c); 47453a5a1b3Sopenharmony_ci pa_assert(in_reply_to); 47553a5a1b3Sopenharmony_ci 47653a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); 47753a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(c, reply, NULL)); 47853a5a1b3Sopenharmony_ci dbus_message_unref(reply); 47953a5a1b3Sopenharmony_ci} 48053a5a1b3Sopenharmony_ci 48153a5a1b3Sopenharmony_civoid pa_dbus_send_basic_value_reply(DBusConnection *c, DBusMessage *in_reply_to, int type, void *data) { 48253a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 48353a5a1b3Sopenharmony_ci 48453a5a1b3Sopenharmony_ci pa_assert(c); 48553a5a1b3Sopenharmony_ci pa_assert(in_reply_to); 48653a5a1b3Sopenharmony_ci pa_assert(dbus_type_is_basic(type)); 48753a5a1b3Sopenharmony_ci pa_assert(data); 48853a5a1b3Sopenharmony_ci 48953a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); 49053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(reply, type, data, DBUS_TYPE_INVALID)); 49153a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(c, reply, NULL)); 49253a5a1b3Sopenharmony_ci dbus_message_unref(reply); 49353a5a1b3Sopenharmony_ci} 49453a5a1b3Sopenharmony_ci 49553a5a1b3Sopenharmony_cistatic const char *signature_from_basic_type(int type) { 49653a5a1b3Sopenharmony_ci switch (type) { 49753a5a1b3Sopenharmony_ci case DBUS_TYPE_BOOLEAN: return DBUS_TYPE_BOOLEAN_AS_STRING; 49853a5a1b3Sopenharmony_ci case DBUS_TYPE_BYTE: return DBUS_TYPE_BYTE_AS_STRING; 49953a5a1b3Sopenharmony_ci case DBUS_TYPE_INT16: return DBUS_TYPE_INT16_AS_STRING; 50053a5a1b3Sopenharmony_ci case DBUS_TYPE_UINT16: return DBUS_TYPE_UINT16_AS_STRING; 50153a5a1b3Sopenharmony_ci case DBUS_TYPE_INT32: return DBUS_TYPE_INT32_AS_STRING; 50253a5a1b3Sopenharmony_ci case DBUS_TYPE_UINT32: return DBUS_TYPE_UINT32_AS_STRING; 50353a5a1b3Sopenharmony_ci case DBUS_TYPE_INT64: return DBUS_TYPE_INT64_AS_STRING; 50453a5a1b3Sopenharmony_ci case DBUS_TYPE_UINT64: return DBUS_TYPE_UINT64_AS_STRING; 50553a5a1b3Sopenharmony_ci case DBUS_TYPE_DOUBLE: return DBUS_TYPE_DOUBLE_AS_STRING; 50653a5a1b3Sopenharmony_ci case DBUS_TYPE_STRING: return DBUS_TYPE_STRING_AS_STRING; 50753a5a1b3Sopenharmony_ci case DBUS_TYPE_OBJECT_PATH: return DBUS_TYPE_OBJECT_PATH_AS_STRING; 50853a5a1b3Sopenharmony_ci case DBUS_TYPE_SIGNATURE: return DBUS_TYPE_SIGNATURE_AS_STRING; 50953a5a1b3Sopenharmony_ci default: pa_assert_not_reached(); 51053a5a1b3Sopenharmony_ci } 51153a5a1b3Sopenharmony_ci} 51253a5a1b3Sopenharmony_ci 51353a5a1b3Sopenharmony_civoid pa_dbus_send_basic_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, int type, void *data) { 51453a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 51553a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 51653a5a1b3Sopenharmony_ci DBusMessageIter variant_iter; 51753a5a1b3Sopenharmony_ci 51853a5a1b3Sopenharmony_ci pa_assert(c); 51953a5a1b3Sopenharmony_ci pa_assert(in_reply_to); 52053a5a1b3Sopenharmony_ci pa_assert(dbus_type_is_basic(type)); 52153a5a1b3Sopenharmony_ci pa_assert(data); 52253a5a1b3Sopenharmony_ci 52353a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); 52453a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 52553a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&msg_iter, 52653a5a1b3Sopenharmony_ci DBUS_TYPE_VARIANT, 52753a5a1b3Sopenharmony_ci signature_from_basic_type(type), 52853a5a1b3Sopenharmony_ci &variant_iter)); 52953a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_basic(&variant_iter, type, data)); 53053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&msg_iter, &variant_iter)); 53153a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(c, reply, NULL)); 53253a5a1b3Sopenharmony_ci dbus_message_unref(reply); 53353a5a1b3Sopenharmony_ci} 53453a5a1b3Sopenharmony_ci 53553a5a1b3Sopenharmony_ci/* Note: returns sizeof(char*) for strings, object paths and signatures. */ 53653a5a1b3Sopenharmony_cistatic unsigned basic_type_size(int type) { 53753a5a1b3Sopenharmony_ci switch (type) { 53853a5a1b3Sopenharmony_ci case DBUS_TYPE_BOOLEAN: return sizeof(dbus_bool_t); 53953a5a1b3Sopenharmony_ci case DBUS_TYPE_BYTE: return 1; 54053a5a1b3Sopenharmony_ci case DBUS_TYPE_INT16: return sizeof(dbus_int16_t); 54153a5a1b3Sopenharmony_ci case DBUS_TYPE_UINT16: return sizeof(dbus_uint16_t); 54253a5a1b3Sopenharmony_ci case DBUS_TYPE_INT32: return sizeof(dbus_int32_t); 54353a5a1b3Sopenharmony_ci case DBUS_TYPE_UINT32: return sizeof(dbus_uint32_t); 54453a5a1b3Sopenharmony_ci case DBUS_TYPE_INT64: return sizeof(dbus_int64_t); 54553a5a1b3Sopenharmony_ci case DBUS_TYPE_UINT64: return sizeof(dbus_uint64_t); 54653a5a1b3Sopenharmony_ci case DBUS_TYPE_DOUBLE: return sizeof(double); 54753a5a1b3Sopenharmony_ci case DBUS_TYPE_STRING: 54853a5a1b3Sopenharmony_ci case DBUS_TYPE_OBJECT_PATH: 54953a5a1b3Sopenharmony_ci case DBUS_TYPE_SIGNATURE: return sizeof(char*); 55053a5a1b3Sopenharmony_ci default: pa_assert_not_reached(); 55153a5a1b3Sopenharmony_ci } 55253a5a1b3Sopenharmony_ci} 55353a5a1b3Sopenharmony_ci 55453a5a1b3Sopenharmony_civoid pa_dbus_send_basic_array_variant_reply( 55553a5a1b3Sopenharmony_ci DBusConnection *c, 55653a5a1b3Sopenharmony_ci DBusMessage *in_reply_to, 55753a5a1b3Sopenharmony_ci int item_type, 55853a5a1b3Sopenharmony_ci void *array, 55953a5a1b3Sopenharmony_ci unsigned n) { 56053a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 56153a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 56253a5a1b3Sopenharmony_ci 56353a5a1b3Sopenharmony_ci pa_assert(c); 56453a5a1b3Sopenharmony_ci pa_assert(in_reply_to); 56553a5a1b3Sopenharmony_ci pa_assert(dbus_type_is_basic(item_type)); 56653a5a1b3Sopenharmony_ci pa_assert(array || n == 0); 56753a5a1b3Sopenharmony_ci 56853a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); 56953a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 57053a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant(&msg_iter, item_type, array, n); 57153a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(c, reply, NULL)); 57253a5a1b3Sopenharmony_ci dbus_message_unref(reply); 57353a5a1b3Sopenharmony_ci} 57453a5a1b3Sopenharmony_ci 57553a5a1b3Sopenharmony_civoid pa_dbus_send_proplist_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, pa_proplist *proplist) { 57653a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 57753a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 57853a5a1b3Sopenharmony_ci 57953a5a1b3Sopenharmony_ci pa_assert(c); 58053a5a1b3Sopenharmony_ci pa_assert(in_reply_to); 58153a5a1b3Sopenharmony_ci pa_assert(proplist); 58253a5a1b3Sopenharmony_ci 58353a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); 58453a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 58553a5a1b3Sopenharmony_ci pa_dbus_append_proplist_variant(&msg_iter, proplist); 58653a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(c, reply, NULL)); 58753a5a1b3Sopenharmony_ci dbus_message_unref(reply); 58853a5a1b3Sopenharmony_ci} 58953a5a1b3Sopenharmony_ci 59053a5a1b3Sopenharmony_civoid pa_dbus_append_basic_array(DBusMessageIter *iter, int item_type, const void *array, unsigned n) { 59153a5a1b3Sopenharmony_ci DBusMessageIter array_iter; 59253a5a1b3Sopenharmony_ci unsigned i; 59353a5a1b3Sopenharmony_ci unsigned item_size; 59453a5a1b3Sopenharmony_ci 59553a5a1b3Sopenharmony_ci pa_assert(iter); 59653a5a1b3Sopenharmony_ci pa_assert(dbus_type_is_basic(item_type)); 59753a5a1b3Sopenharmony_ci pa_assert(array || n == 0); 59853a5a1b3Sopenharmony_ci 59953a5a1b3Sopenharmony_ci item_size = basic_type_size(item_type); 60053a5a1b3Sopenharmony_ci 60153a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, signature_from_basic_type(item_type), &array_iter)); 60253a5a1b3Sopenharmony_ci 60353a5a1b3Sopenharmony_ci for (i = 0; i < n; ++i) 60453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_basic(&array_iter, item_type, &((uint8_t*) array)[i * item_size])); 60553a5a1b3Sopenharmony_ci 60653a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(iter, &array_iter)); 60753a5a1b3Sopenharmony_ci} 60853a5a1b3Sopenharmony_ci 60953a5a1b3Sopenharmony_civoid pa_dbus_append_basic_variant(DBusMessageIter *iter, int type, void *data) { 61053a5a1b3Sopenharmony_ci DBusMessageIter variant_iter; 61153a5a1b3Sopenharmony_ci 61253a5a1b3Sopenharmony_ci pa_assert(iter); 61353a5a1b3Sopenharmony_ci pa_assert(dbus_type_is_basic(type)); 61453a5a1b3Sopenharmony_ci pa_assert(data); 61553a5a1b3Sopenharmony_ci 61653a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, signature_from_basic_type(type), &variant_iter)); 61753a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_basic(&variant_iter, type, data)); 61853a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); 61953a5a1b3Sopenharmony_ci} 62053a5a1b3Sopenharmony_ci 62153a5a1b3Sopenharmony_civoid pa_dbus_append_basic_array_variant(DBusMessageIter *iter, int item_type, const void *array, unsigned n) { 62253a5a1b3Sopenharmony_ci DBusMessageIter variant_iter; 62353a5a1b3Sopenharmony_ci char *array_signature; 62453a5a1b3Sopenharmony_ci 62553a5a1b3Sopenharmony_ci pa_assert(iter); 62653a5a1b3Sopenharmony_ci pa_assert(dbus_type_is_basic(item_type)); 62753a5a1b3Sopenharmony_ci pa_assert(array || n == 0); 62853a5a1b3Sopenharmony_ci 62953a5a1b3Sopenharmony_ci array_signature = pa_sprintf_malloc("a%c", *signature_from_basic_type(item_type)); 63053a5a1b3Sopenharmony_ci 63153a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, array_signature, &variant_iter)); 63253a5a1b3Sopenharmony_ci pa_dbus_append_basic_array(&variant_iter, item_type, array, n); 63353a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); 63453a5a1b3Sopenharmony_ci 63553a5a1b3Sopenharmony_ci pa_xfree(array_signature); 63653a5a1b3Sopenharmony_ci} 63753a5a1b3Sopenharmony_ci 63853a5a1b3Sopenharmony_civoid pa_dbus_append_basic_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, int type, void *data) { 63953a5a1b3Sopenharmony_ci DBusMessageIter dict_entry_iter; 64053a5a1b3Sopenharmony_ci 64153a5a1b3Sopenharmony_ci pa_assert(dict_iter); 64253a5a1b3Sopenharmony_ci pa_assert(key); 64353a5a1b3Sopenharmony_ci pa_assert(dbus_type_is_basic(type)); 64453a5a1b3Sopenharmony_ci pa_assert(data); 64553a5a1b3Sopenharmony_ci 64653a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); 64753a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); 64853a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant(&dict_entry_iter, type, data); 64953a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); 65053a5a1b3Sopenharmony_ci} 65153a5a1b3Sopenharmony_ci 65253a5a1b3Sopenharmony_civoid pa_dbus_append_basic_array_variant_dict_entry( 65353a5a1b3Sopenharmony_ci DBusMessageIter *dict_iter, 65453a5a1b3Sopenharmony_ci const char *key, 65553a5a1b3Sopenharmony_ci int item_type, 65653a5a1b3Sopenharmony_ci const void *array, 65753a5a1b3Sopenharmony_ci unsigned n) { 65853a5a1b3Sopenharmony_ci DBusMessageIter dict_entry_iter; 65953a5a1b3Sopenharmony_ci 66053a5a1b3Sopenharmony_ci pa_assert(dict_iter); 66153a5a1b3Sopenharmony_ci pa_assert(key); 66253a5a1b3Sopenharmony_ci pa_assert(dbus_type_is_basic(item_type)); 66353a5a1b3Sopenharmony_ci pa_assert(array || n == 0); 66453a5a1b3Sopenharmony_ci 66553a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); 66653a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); 66753a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant(&dict_entry_iter, item_type, array, n); 66853a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); 66953a5a1b3Sopenharmony_ci} 67053a5a1b3Sopenharmony_ci 67153a5a1b3Sopenharmony_civoid pa_dbus_append_proplist(DBusMessageIter *iter, pa_proplist *proplist) { 67253a5a1b3Sopenharmony_ci DBusMessageIter dict_iter; 67353a5a1b3Sopenharmony_ci DBusMessageIter dict_entry_iter; 67453a5a1b3Sopenharmony_ci DBusMessageIter array_iter; 67553a5a1b3Sopenharmony_ci void *state = NULL; 67653a5a1b3Sopenharmony_ci const char *key; 67753a5a1b3Sopenharmony_ci 67853a5a1b3Sopenharmony_ci pa_assert(iter); 67953a5a1b3Sopenharmony_ci pa_assert(proplist); 68053a5a1b3Sopenharmony_ci 68153a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{say}", &dict_iter)); 68253a5a1b3Sopenharmony_ci 68353a5a1b3Sopenharmony_ci while ((key = pa_proplist_iterate(proplist, &state))) { 68453a5a1b3Sopenharmony_ci const void *value = NULL; 68553a5a1b3Sopenharmony_ci size_t nbytes; 68653a5a1b3Sopenharmony_ci 68753a5a1b3Sopenharmony_ci pa_assert_se(pa_proplist_get(proplist, key, &value, &nbytes) >= 0); 68853a5a1b3Sopenharmony_ci 68953a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); 69053a5a1b3Sopenharmony_ci 69153a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); 69253a5a1b3Sopenharmony_ci 69353a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&dict_entry_iter, DBUS_TYPE_ARRAY, "y", &array_iter)); 69453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE, &value, nbytes)); 69553a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&dict_entry_iter, &array_iter)); 69653a5a1b3Sopenharmony_ci 69753a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)); 69853a5a1b3Sopenharmony_ci } 69953a5a1b3Sopenharmony_ci 70053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(iter, &dict_iter)); 70153a5a1b3Sopenharmony_ci} 70253a5a1b3Sopenharmony_ci 70353a5a1b3Sopenharmony_civoid pa_dbus_append_proplist_variant(DBusMessageIter *iter, pa_proplist *proplist) { 70453a5a1b3Sopenharmony_ci DBusMessageIter variant_iter; 70553a5a1b3Sopenharmony_ci 70653a5a1b3Sopenharmony_ci pa_assert(iter); 70753a5a1b3Sopenharmony_ci pa_assert(proplist); 70853a5a1b3Sopenharmony_ci 70953a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{say}", &variant_iter)); 71053a5a1b3Sopenharmony_ci pa_dbus_append_proplist(&variant_iter, proplist); 71153a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); 71253a5a1b3Sopenharmony_ci} 71353a5a1b3Sopenharmony_ci 71453a5a1b3Sopenharmony_civoid pa_dbus_append_proplist_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, pa_proplist *proplist) { 71553a5a1b3Sopenharmony_ci DBusMessageIter dict_entry_iter; 71653a5a1b3Sopenharmony_ci 71753a5a1b3Sopenharmony_ci pa_assert(dict_iter); 71853a5a1b3Sopenharmony_ci pa_assert(key); 71953a5a1b3Sopenharmony_ci pa_assert(proplist); 72053a5a1b3Sopenharmony_ci 72153a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); 72253a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); 72353a5a1b3Sopenharmony_ci pa_dbus_append_proplist_variant(&dict_entry_iter, proplist); 72453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); 72553a5a1b3Sopenharmony_ci} 72653a5a1b3Sopenharmony_ci 72753a5a1b3Sopenharmony_cipa_proplist *pa_dbus_get_proplist_arg(DBusConnection *c, DBusMessage *msg, DBusMessageIter *iter) { 72853a5a1b3Sopenharmony_ci DBusMessageIter dict_iter; 72953a5a1b3Sopenharmony_ci DBusMessageIter dict_entry_iter; 73053a5a1b3Sopenharmony_ci char *signature; 73153a5a1b3Sopenharmony_ci pa_proplist *proplist = NULL; 73253a5a1b3Sopenharmony_ci const char *key = NULL; 73353a5a1b3Sopenharmony_ci const uint8_t *value = NULL; 73453a5a1b3Sopenharmony_ci int value_length = 0; 73553a5a1b3Sopenharmony_ci 73653a5a1b3Sopenharmony_ci pa_assert(c); 73753a5a1b3Sopenharmony_ci pa_assert(msg); 73853a5a1b3Sopenharmony_ci pa_assert(iter); 73953a5a1b3Sopenharmony_ci 74053a5a1b3Sopenharmony_ci pa_assert_se(signature = dbus_message_iter_get_signature(iter)); 74153a5a1b3Sopenharmony_ci pa_assert_se(pa_streq(signature, "a{say}")); 74253a5a1b3Sopenharmony_ci 74353a5a1b3Sopenharmony_ci dbus_free(signature); 74453a5a1b3Sopenharmony_ci 74553a5a1b3Sopenharmony_ci proplist = pa_proplist_new(); 74653a5a1b3Sopenharmony_ci 74753a5a1b3Sopenharmony_ci dbus_message_iter_recurse(iter, &dict_iter); 74853a5a1b3Sopenharmony_ci 74953a5a1b3Sopenharmony_ci while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) { 75053a5a1b3Sopenharmony_ci dbus_message_iter_recurse(&dict_iter, &dict_entry_iter); 75153a5a1b3Sopenharmony_ci 75253a5a1b3Sopenharmony_ci dbus_message_iter_get_basic(&dict_entry_iter, &key); 75353a5a1b3Sopenharmony_ci dbus_message_iter_next(&dict_entry_iter); 75453a5a1b3Sopenharmony_ci 75553a5a1b3Sopenharmony_ci if (strlen(key) <= 0 || !pa_ascii_valid(key)) { 75653a5a1b3Sopenharmony_ci pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Invalid property list key: '%s'.", key); 75753a5a1b3Sopenharmony_ci goto fail; 75853a5a1b3Sopenharmony_ci } 75953a5a1b3Sopenharmony_ci 76053a5a1b3Sopenharmony_ci dbus_message_iter_get_fixed_array(&dict_entry_iter, &value, &value_length); 76153a5a1b3Sopenharmony_ci 76253a5a1b3Sopenharmony_ci pa_assert(value_length >= 0); 76353a5a1b3Sopenharmony_ci 76453a5a1b3Sopenharmony_ci pa_assert_se(pa_proplist_set(proplist, key, value, value_length) >= 0); 76553a5a1b3Sopenharmony_ci 76653a5a1b3Sopenharmony_ci dbus_message_iter_next(&dict_iter); 76753a5a1b3Sopenharmony_ci } 76853a5a1b3Sopenharmony_ci 76953a5a1b3Sopenharmony_ci dbus_message_iter_next(iter); 77053a5a1b3Sopenharmony_ci 77153a5a1b3Sopenharmony_ci return proplist; 77253a5a1b3Sopenharmony_ci 77353a5a1b3Sopenharmony_cifail: 77453a5a1b3Sopenharmony_ci if (proplist) 77553a5a1b3Sopenharmony_ci pa_proplist_free(proplist); 77653a5a1b3Sopenharmony_ci 77753a5a1b3Sopenharmony_ci return NULL; 77853a5a1b3Sopenharmony_ci} 779