From eb93e2537a60db963bac84e189c52b3d83521c63 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Thu, 19 Mar 2009 01:35:02 +0200 Subject: dbus: split dbus-util into dbus-shared modules: fix dbus-util include pulse: get dbus at context connection --- src/Makefile.am | 36 +- src/modules/bluetooth/bluetooth-util.c | 2 +- src/modules/bluetooth/module-bluetooth-device.c | 3 +- src/modules/bluetooth/module-bluetooth-discover.c | 2 +- src/modules/bluetooth/module-bluetooth-proximity.c | 2 +- src/modules/dbus-util.c | 437 --------------------- src/modules/dbus-util.h | 68 ---- src/modules/hal-util.c | 2 +- src/modules/module-console-kit.c | 2 +- src/modules/module-hal-detect.c | 2 +- src/modules/reserve-wrap.c | 3 +- src/pulsecore/dbus-shared.c | 111 ++++++ src/pulsecore/dbus-shared.h | 42 ++ src/pulsecore/dbus-util.c | 397 +++++++++++++++++++ src/pulsecore/dbus-util.h | 63 +++ 15 files changed, 642 insertions(+), 530 deletions(-) delete mode 100644 src/modules/dbus-util.c delete mode 100644 src/modules/dbus-util.h create mode 100644 src/pulsecore/dbus-shared.c create mode 100644 src/pulsecore/dbus-shared.h create mode 100644 src/pulsecore/dbus-util.c create mode 100644 src/pulsecore/dbus-util.h diff --git a/src/Makefile.am b/src/Makefile.am index a99e2756..0d4f53af 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -633,6 +633,12 @@ if OS_IS_WIN32 libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/dllmain.c endif +if HAVE_DBUS +libpulsecommon_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/dbus-util.c pulsecore/dbus-util.h +libpulsecommon_@PA_MAJORMINORMICRO@_la_CFLAGS += $(DBUS_CFLAGS) +libpulsecommon_@PA_MAJORMINORMICRO@_la_LIBADD += $(DBUS_LIBS) +endif + ################################### # Client library # ################################### @@ -713,7 +719,7 @@ libpulse_la_SOURCES = \ pulse/volume.c pulse/volume.h \ pulse/xmalloc.c pulse/xmalloc.h -libpulse_la_CFLAGS = $(AM_CFLAGS) +libpulse_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LTLIBICONV) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse_la_LDFLAGS = $(AM_LDFLAGS) $(VERSIONING_LDFLAGS) -version-info $(LIBPULSE_VERSION_INFO) @@ -813,6 +819,13 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS += $(X11_CFLAGS) libpulsecore_@PA_MAJORMINORMICRO@_la_LDFLAGS += $(X11_LIBS) endif + +if HAVE_DBUS +libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/dbus-shared.c pulsecore/dbus-shared.h +libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS += $(DBUS_CFLAGS) +libpulsecore_@PA_MAJORMINORMICRO@_la_LIBADD += $(DBUS_LIBS) +endif + # We split the foreign code off to not be annoyed by warnings we don't care about noinst_LTLIBRARIES = libpulsecore-foreign.la @@ -902,7 +915,6 @@ libavahi_wrap_la_LIBADD = $(AM_LIBADD) $(AVAHI_CFLAGS) libpulsecore-@PA_MAJORMIN if HAVE_DBUS # Serveral module (e.g. libalsa-util.la) modlibexec_LTLIBRARIES += \ - libdbus-util.la \ module-console-kit.la endif @@ -1322,7 +1334,7 @@ endif if HAVE_DBUS libalsa_util_la_SOURCES += modules/reserve.h modules/reserve.c modules/reserve-wrap.c modules/reserve-wrap.h -libalsa_util_la_LIBADD += $(DBUS_LIBS) libdbus-util.la +libalsa_util_la_LIBADD += $(DBUS_LIBS) libalsa_util_la_CFLAGS += $(DBUS_CFLAGS) endif @@ -1476,20 +1488,14 @@ module_jack_source_la_LDFLAGS = $(MODULE_LDFLAGS) module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la $(JACK_LIBS) libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_jack_source_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) -# HAL/D-Bus -libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h -libdbus_util_la_LDFLAGS = -avoid-version -libdbus_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la -libdbus_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) - module_hal_detect_la_SOURCES = modules/module-hal-detect.c module_hal_detect_la_LDFLAGS = $(MODULE_LDFLAGS) -module_hal_detect_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_hal_detect_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_hal_detect_la_CFLAGS = $(AM_CFLAGS) $(HAL_CFLAGS) module_console_kit_la_SOURCES = modules/module-console-kit.c module_console_kit_la_LDFLAGS = $(MODULE_LDFLAGS) -module_console_kit_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_console_kit_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_console_kit_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) # GConf support @@ -1506,7 +1512,7 @@ gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) # Bluetooth proximity module_bluetooth_proximity_la_SOURCES = modules/bluetooth/module-bluetooth-proximity.c module_bluetooth_proximity_la_LDFLAGS = $(MODULE_LDFLAGS) -module_bluetooth_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_bluetooth_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_bluetooth_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_BT_PROXIMITY_HELPER=\"$(pulselibexecdir)/proximity-helper\" proximity_helper_SOURCES = modules/bluetooth/proximity-helper.c @@ -1517,7 +1523,7 @@ proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) # Bluetooth sink / source module_bluetooth_discover_la_SOURCES = modules/bluetooth/module-bluetooth-discover.c module_bluetooth_discover_la_LDFLAGS = $(MODULE_LDFLAGS) -module_bluetooth_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libbluetooth-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_bluetooth_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libbluetooth-util.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) libbluetooth_sbc_la_SOURCES = modules/bluetooth/sbc.c modules/bluetooth/sbc.h modules/bluetooth/sbc_tables.h modules/bluetooth/sbc_math.h modules/bluetooth/sbc_primitives.h modules/bluetooth/sbc_primitives.c modules/bluetooth/sbc_primitives_mmx.h modules/bluetooth/sbc_primitives_neon.h modules/bluetooth/sbc_primitives_mmx.c modules/bluetooth/sbc_primitives_neon.c @@ -1534,12 +1540,12 @@ BLUETOOTH_IPC_FILES = $(subst modules/bluetooth/,,$(libbluetooth_ipc_la_SOURCES) libbluetooth_util_la_SOURCES = modules/bluetooth/bluetooth-util.c modules/bluetooth/bluetooth-util.h libbluetooth_util_la_LDFLAGS = -avoid-version -libbluetooth_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libdbus-util.la +libbluetooth_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la libbluetooth_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c modules/bluetooth/rtp.h module_bluetooth_device_la_LDFLAGS = $(MODULE_LDFLAGS) -module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libdbus-util.la libbluetooth-util.la libbluetooth-ipc.la libbluetooth-sbc.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libbluetooth-util.la libbluetooth-ipc.la libbluetooth-sbc.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) # Apple Airtunes/RAOP diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index 3dfc65e7..1cdade99 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include "bluetooth-util.h" diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 2500fb09..2ff64ba9 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -46,8 +46,7 @@ #include #include #include - -#include +#include #include "module-bluetooth-device-symdef.h" #include "ipc.h" diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c index 3288cc55..46f8b723 100644 --- a/src/modules/bluetooth/module-bluetooth-discover.c +++ b/src/modules/bluetooth/module-bluetooth-discover.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "module-bluetooth-discover-symdef.h" #include "bluetooth-util.h" diff --git a/src/modules/bluetooth/module-bluetooth-proximity.c b/src/modules/bluetooth/module-bluetooth-proximity.c index c8d7b4d9..9993c8dc 100644 --- a/src/modules/bluetooth/module-bluetooth-proximity.c +++ b/src/modules/bluetooth/module-bluetooth-proximity.c @@ -42,8 +42,8 @@ #include #include #include +#include -#include "../dbus-util.h" #include "module-bluetooth-proximity-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering"); diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c deleted file mode 100644 index e2d45803..00000000 --- a/src/modules/dbus-util.c +++ /dev/null @@ -1,437 +0,0 @@ -/*** - This file is part of PulseAudio. - - Copyright 2006 Lennart Poettering - Copyright 2006 Shams E. King - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of the License, - or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include - -#include "dbus-util.h" - -struct pa_dbus_connection { - PA_REFCNT_DECLARE; - - pa_core *core; - DBusConnection *connection; - const char *property_name; - pa_defer_event* dispatch_event; -}; - -static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) { - DBusConnection *conn = userdata; - - if (dbus_connection_dispatch(conn) == DBUS_DISPATCH_COMPLETE) { - /* no more data to process, disable the deferred */ - ea->defer_enable(ev, 0); - } -} - -/* DBusDispatchStatusFunction callback for the pa mainloop */ -static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, void *userdata) { - pa_dbus_connection *c = userdata; - - pa_assert(c); - - switch(status) { - - case DBUS_DISPATCH_COMPLETE: - c->core->mainloop->defer_enable(c->dispatch_event, 0); - break; - - case DBUS_DISPATCH_DATA_REMAINS: - case DBUS_DISPATCH_NEED_MEMORY: - default: - c->core->mainloop->defer_enable(c->dispatch_event, 1); - break; - } -} - -static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) { - unsigned int flags; - pa_io_event_flags_t events = 0; - - pa_assert(watch); - - flags = dbus_watch_get_flags(watch); - - /* no watch flags for disabled watches */ - if (!dbus_watch_get_enabled(watch)) - return PA_IO_EVENT_NULL; - - if (flags & DBUS_WATCH_READABLE) - events |= PA_IO_EVENT_INPUT; - if (flags & DBUS_WATCH_WRITABLE) - events |= PA_IO_EVENT_OUTPUT; - - return events | PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR; -} - -/* pa_io_event_cb_t IO event handler */ -static void handle_io_event(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) { - unsigned int flags = 0; - DBusWatch *watch = userdata; - -#if HAVE_DBUS_WATCH_GET_UNIX_FD - pa_assert(fd == dbus_watch_get_unix_fd(watch)); -#else - pa_assert(fd == dbus_watch_get_fd(watch)); -#endif - - if (!dbus_watch_get_enabled(watch)) { - pa_log_warn("Asked to handle disabled watch: %p %i", (void*) watch, fd); - return; - } - - if (events & PA_IO_EVENT_INPUT) - flags |= DBUS_WATCH_READABLE; - if (events & PA_IO_EVENT_OUTPUT) - flags |= DBUS_WATCH_WRITABLE; - if (events & PA_IO_EVENT_HANGUP) - flags |= DBUS_WATCH_HANGUP; - if (events & PA_IO_EVENT_ERROR) - flags |= DBUS_WATCH_ERROR; - - dbus_watch_handle(watch, flags); -} - -/* pa_time_event_cb_t timer event handler */ -static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *tv, void *userdata) { - DBusTimeout *timeout = userdata; - - if (dbus_timeout_get_enabled(timeout)) { - struct timeval next = *tv; - dbus_timeout_handle(timeout); - - /* restart it for the next scheduled time */ - pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - ea->time_restart(e, &next); - } -} - -/* DBusAddWatchFunction callback for pa mainloop */ -static dbus_bool_t add_watch(DBusWatch *watch, void *data) { - pa_core *c = PA_CORE(data); - pa_io_event *ev; - - pa_assert(watch); - pa_assert(c); - - ev = c->mainloop->io_new( - c->mainloop, -#if HAVE_DBUS_WATCH_GET_UNIX_FD - dbus_watch_get_unix_fd(watch), -#else - dbus_watch_get_fd(watch), -#endif - get_watch_flags(watch), handle_io_event, watch); - - dbus_watch_set_data(watch, ev, NULL); - - return TRUE; -} - -/* DBusRemoveWatchFunction callback for pa mainloop */ -static void remove_watch(DBusWatch *watch, void *data) { - pa_core *c = PA_CORE(data); - pa_io_event *ev; - - pa_assert(watch); - pa_assert(c); - - if ((ev = dbus_watch_get_data(watch))) - c->mainloop->io_free(ev); -} - -/* DBusWatchToggledFunction callback for pa mainloop */ -static void toggle_watch(DBusWatch *watch, void *data) { - pa_core *c = PA_CORE(data); - pa_io_event *ev; - - pa_assert(watch); - pa_core_assert_ref(c); - - pa_assert_se(ev = dbus_watch_get_data(watch)); - - /* get_watch_flags() checks if the watch is enabled */ - c->mainloop->io_enable(ev, get_watch_flags(watch)); -} - -/* DBusAddTimeoutFunction callback for pa mainloop */ -static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { - pa_core *c = PA_CORE(data); - pa_time_event *ev; - struct timeval tv; - - pa_assert(timeout); - pa_assert(c); - - if (!dbus_timeout_get_enabled(timeout)) - return FALSE; - - pa_gettimeofday(&tv); - pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - - ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout); - - dbus_timeout_set_data(timeout, ev, NULL); - - return TRUE; -} - -/* DBusRemoveTimeoutFunction callback for pa mainloop */ -static void remove_timeout(DBusTimeout *timeout, void *data) { - pa_core *c = PA_CORE(data); - pa_time_event *ev; - - pa_assert(timeout); - pa_assert(c); - - if ((ev = dbus_timeout_get_data(timeout))) - c->mainloop->time_free(ev); -} - -/* DBusTimeoutToggledFunction callback for pa mainloop */ -static void toggle_timeout(DBusTimeout *timeout, void *data) { - pa_core *c = PA_CORE(data); - pa_time_event *ev; - - pa_assert(timeout); - pa_assert(c); - - pa_assert_se(ev = dbus_timeout_get_data(timeout)); - - if (dbus_timeout_get_enabled(timeout)) { - struct timeval tv; - - pa_gettimeofday(&tv); - pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); - - c->mainloop->time_restart(ev, &tv); - } else - c->mainloop->time_restart(ev, NULL); -} - -static void wakeup_main(void *userdata) { - pa_dbus_connection *c = userdata; - - pa_assert(c); - - /* this will wakeup the mainloop and dispatch events, although - * it may not be the cleanest way of accomplishing it */ - c->core->mainloop->defer_enable(c->dispatch_event, 1); -} - -static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name) { - pa_dbus_connection *pconn; - - pconn = pa_xnew(pa_dbus_connection, 1); - PA_REFCNT_INIT(pconn); - pconn->core = c; - pconn->property_name = name; - pconn->connection = conn; - pconn->dispatch_event = c->mainloop->defer_new(c->mainloop, dispatch_cb, conn); - - pa_shared_set(c, name, pconn); - - return pconn; -} - -DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c){ - pa_assert(c); - pa_assert(PA_REFCNT_VALUE(c) > 0); - pa_assert(c->connection); - - return c->connection; -} - -void pa_dbus_connection_unref(pa_dbus_connection *c) { - pa_assert(c); - pa_assert(PA_REFCNT_VALUE(c) > 0); - - if (PA_REFCNT_DEC(c) > 0) - return; - - if (dbus_connection_get_is_connected(c->connection)) { - dbus_connection_close(c->connection); - /* must process remaining messages, bit of a kludge to handle - * both unload and shutdown */ - while (dbus_connection_read_write_dispatch(c->connection, -1)); - } - - /* already disconnected, just free */ - pa_shared_remove(c->core, c->property_name); - c->core->mainloop->defer_free(c->dispatch_event); - dbus_connection_unref(c->connection); - pa_xfree(c); -} - -pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) { - pa_assert(c); - pa_assert(PA_REFCNT_VALUE(c) > 0); - - PA_REFCNT_INC(c); - - return c; -} - -pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error) { - - static const char *const prop_name[] = { - [DBUS_BUS_SESSION] = "dbus-connection-session", - [DBUS_BUS_SYSTEM] = "dbus-connection-system", - [DBUS_BUS_STARTER] = "dbus-connection-starter" - }; - DBusConnection *conn; - pa_dbus_connection *pconn; - - pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER); - - if ((pconn = pa_shared_get(c, prop_name[type]))) - return pa_dbus_connection_ref(pconn); - - if (!(conn = dbus_bus_get_private(type, error))) - return NULL; - - pconn = pa_dbus_connection_new(c, conn, prop_name[type]); - - dbus_connection_set_exit_on_disconnect(conn, FALSE); - dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL); - dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, c, NULL); - dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, c, NULL); - dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL); - - return pconn; -} - -int pa_dbus_add_matches(DBusConnection *c, DBusError *error, ...) { - const char *t; - va_list ap; - unsigned k = 0; - - pa_assert(c); - pa_assert(error); - - va_start(ap, error); - while ((t = va_arg(ap, const char*))) { - dbus_bus_add_match(c, t, error); - - if (dbus_error_is_set(error)) - goto fail; - - k++; - } - va_end(ap); - return 0; - -fail: - - va_end(ap); - va_start(ap, error); - for (; k > 0; k--) { - DBusError e; - - pa_assert_se(t = va_arg(ap, const char*)); - - dbus_error_init(&e); - dbus_bus_remove_match(c, t, &e); - dbus_error_free(&e); - } - va_end(ap); - - return -1; -} - -void pa_dbus_remove_matches(DBusConnection *c, ...) { - const char *t; - va_list ap; - DBusError error; - - pa_assert(c); - - dbus_error_init(&error); - - va_start(ap, c); - while ((t = va_arg(ap, const char*))) { - dbus_bus_remove_match(c, t, &error); - dbus_error_free(&error); - } - va_end(ap); -} - -pa_dbus_pending *pa_dbus_pending_new( - DBusConnection *c, - DBusMessage *m, - DBusPendingCall *pending, - void *context_data, - void *call_data) { - - pa_dbus_pending *p; - - pa_assert(pending); - - p = pa_xnew(pa_dbus_pending, 1); - p->connection = c; - p->message = m; - p->pending = pending; - p->context_data = context_data; - p->call_data = call_data; - - PA_LLIST_INIT(pa_dbus_pending, p); - - return p; -} - -void pa_dbus_pending_free(pa_dbus_pending *p) { - pa_assert(p); - - if (p->pending) - dbus_pending_call_cancel(p->pending); /* p->pending is freed by cancel() */ - - if (p->message) - dbus_message_unref(p->message); - - pa_xfree(p); -} - -void pa_dbus_sync_pending_list(pa_dbus_pending **p) { - pa_assert(p); - - while (*p && dbus_connection_read_write_dispatch((*p)->connection, -1)) - ; -} - -void pa_dbus_free_pending_list(pa_dbus_pending **p) { - pa_dbus_pending *i; - - pa_assert(p); - - while ((i = *p)) { - PA_LLIST_REMOVE(pa_dbus_pending, *p, i); - pa_dbus_pending_free(i); - } -} diff --git a/src/modules/dbus-util.h b/src/modules/dbus-util.h deleted file mode 100644 index 554f41a4..00000000 --- a/src/modules/dbus-util.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef foodbusutilhfoo -#define foodbusutilhfoo - -/*** - This file is part of PulseAudio. - - Copyright 2006 Shams E. King - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of the License, - or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with PulseAudio; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -#include -#include - -typedef struct pa_dbus_connection pa_dbus_connection; - -/* return the DBusConnection of the specified type for the given core, - * like dbus_bus_get(), but integrates the connection with the pa_core */ -pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error); - -DBusConnection* pa_dbus_connection_get(pa_dbus_connection *conn); - -pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *conn); -void pa_dbus_connection_unref(pa_dbus_connection *conn); - -int pa_dbus_add_matches(DBusConnection *c, DBusError *error, ...) PA_GCC_SENTINEL; -void pa_dbus_remove_matches(DBusConnection *c, ...) PA_GCC_SENTINEL; - -typedef struct pa_dbus_pending pa_dbus_pending; - -struct userdata; /* We leave the actual definition to the caller */ - -struct pa_dbus_pending { - DBusConnection *connection; - DBusMessage *message; - DBusPendingCall *pending; - - void *context_data; - void *call_data; - - PA_LLIST_FIELDS(pa_dbus_pending); -}; - -pa_dbus_pending *pa_dbus_pending_new(DBusConnection *c, DBusMessage *m, DBusPendingCall *pending, void *context_data, void *call_data); -void pa_dbus_pending_free(pa_dbus_pending *p); - -/* Sync up a list of pa_dbus_pending_call objects */ -void pa_dbus_sync_pending_list(pa_dbus_pending **p); - -/* Free up a list of pa_dbus_pending_call objects */ -void pa_dbus_free_pending_list(pa_dbus_pending **p); - -#endif diff --git a/src/modules/hal-util.c b/src/modules/hal-util.c index 422ae4ec..e2a2d8d7 100644 --- a/src/modules/hal-util.c +++ b/src/modules/hal-util.c @@ -24,10 +24,10 @@ #endif #include +#include #include -#include "dbus-util.h" #include "hal-util.h" int pa_hal_get_info(pa_core *core, pa_proplist *p, int card) { diff --git a/src/modules/module-console-kit.c b/src/modules/module-console-kit.c index 3fba7ef6..a666073c 100644 --- a/src/modules/module-console-kit.c +++ b/src/modules/module-console-kit.c @@ -44,8 +44,8 @@ #include #include #include +#include -#include "dbus-util.h" #include "module-console-kit-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering"); diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 9b0d71c9..0dd22cbd 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -45,10 +45,10 @@ #include #include #include +#include #include -#include "dbus-util.h" #include "module-hal-detect-symdef.h" PA_MODULE_AUTHOR("Shahms King"); diff --git a/src/modules/reserve-wrap.c b/src/modules/reserve-wrap.c index c956673b..1927342b 100644 --- a/src/modules/reserve-wrap.c +++ b/src/modules/reserve-wrap.c @@ -29,8 +29,7 @@ #include #include #include - -#include +#include #include "reserve.h" #include "reserve-wrap.h" diff --git a/src/pulsecore/dbus-shared.c b/src/pulsecore/dbus-shared.c new file mode 100644 index 00000000..b52c14cb --- /dev/null +++ b/src/pulsecore/dbus-shared.c @@ -0,0 +1,111 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2006, 2009 Lennart Poettering + Copyright 2006 Shams E. King + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include + +#include "dbus-shared.h" + +struct pa_dbus_connection { + PA_REFCNT_DECLARE; + + pa_dbus_wrap_connection *connection; + pa_core *core; + const char *property_name; +}; + +static pa_dbus_connection* pa_dbus_connection_new(pa_core *c, pa_dbus_wrap_connection *conn, const char *name) { + pa_dbus_connection *pconn; + + pconn = pa_xnew(pa_dbus_connection, 1); + PA_REFCNT_INIT(pconn); + pconn->core = c; + pconn->property_name = name; + pconn->connection = conn; + + pa_shared_set(c, name, pconn); + + return pconn; +} + +pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error) { + + static const char *const prop_name[] = { + [DBUS_BUS_SESSION] = "dbus-connection-session", + [DBUS_BUS_SYSTEM] = "dbus-connection-system", + [DBUS_BUS_STARTER] = "dbus-connection-starter" + }; + pa_dbus_wrap_connection *conn; + pa_dbus_connection *pconn; + + pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER); + + if ((pconn = pa_shared_get(c, prop_name[type]))) + return pa_dbus_connection_ref(pconn); + + if (!(conn = pa_dbus_wrap_connection_new(c->mainloop, type, error))) + return NULL; + + pconn = pa_dbus_connection_new(c, conn, prop_name[type]); + + return pconn; +} + +DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c){ + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) > 0); + pa_assert(c->connection); + + return pa_dbus_wrap_connection_get(c->connection); +} + +void pa_dbus_connection_unref(pa_dbus_connection *c) { + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) > 0); + + if (PA_REFCNT_DEC(c) > 0) + return; + + /* already disconnected, just free */ + pa_shared_remove(c->core, c->property_name); + pa_xfree(c); +} + +pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) { + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) > 0); + + PA_REFCNT_INC(c); + + return c; +} + + + diff --git a/src/pulsecore/dbus-shared.h b/src/pulsecore/dbus-shared.h new file mode 100644 index 00000000..4c154552 --- /dev/null +++ b/src/pulsecore/dbus-shared.h @@ -0,0 +1,42 @@ +#ifndef foodbussharedhfoo +#define foodbussharedhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2004-2006, 2009 Lennart Poettering + Copyright 2006 Shams E. King + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include +#include + +typedef struct pa_dbus_connection pa_dbus_connection; + +/* return a pa_dbus_connection of the specified type for the given core, + * like dbus_bus_get(), but integrates the connection with the pa_core */ +pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error); + +DBusConnection* pa_dbus_connection_get(pa_dbus_connection *conn); + +pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *conn); +void pa_dbus_connection_unref(pa_dbus_connection *conn); + +#endif diff --git a/src/pulsecore/dbus-util.c b/src/pulsecore/dbus-util.c new file mode 100644 index 00000000..d712bff3 --- /dev/null +++ b/src/pulsecore/dbus-util.c @@ -0,0 +1,397 @@ +/*** + This file is part of PulseAudio. + + Copyright 2006 Lennart Poettering + Copyright 2006 Shams E. King + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include + +#include "dbus-util.h" + +struct pa_dbus_wrap_connection { + pa_mainloop_api *mainloop; + DBusConnection *connection; + pa_defer_event* dispatch_event; +}; + +static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata) { + DBusConnection *conn = userdata; + + if (dbus_connection_dispatch(conn) == DBUS_DISPATCH_COMPLETE) { + /* no more data to process, disable the deferred */ + ea->defer_enable(ev, 0); + } +} + +/* DBusDispatchStatusFunction callback for the pa mainloop */ +static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, void *userdata) { + pa_dbus_wrap_connection *c = userdata; + + pa_assert(c); + + switch(status) { + + case DBUS_DISPATCH_COMPLETE: + c->mainloop->defer_enable(c->dispatch_event, 0); + break; + + case DBUS_DISPATCH_DATA_REMAINS: + case DBUS_DISPATCH_NEED_MEMORY: + default: + c->mainloop->defer_enable(c->dispatch_event, 1); + break; + } +} + +static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) { + unsigned int flags; + pa_io_event_flags_t events = 0; + + pa_assert(watch); + + flags = dbus_watch_get_flags(watch); + + /* no watch flags for disabled watches */ + if (!dbus_watch_get_enabled(watch)) + return PA_IO_EVENT_NULL; + + if (flags & DBUS_WATCH_READABLE) + events |= PA_IO_EVENT_INPUT; + if (flags & DBUS_WATCH_WRITABLE) + events |= PA_IO_EVENT_OUTPUT; + + return events | PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR; +} + +/* pa_io_event_cb_t IO event handler */ +static void handle_io_event(pa_mainloop_api *ea, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) { + unsigned int flags = 0; + DBusWatch *watch = userdata; + +#if HAVE_DBUS_WATCH_GET_UNIX_FD + pa_assert(fd == dbus_watch_get_unix_fd(watch)); +#else + pa_assert(fd == dbus_watch_get_fd(watch)); +#endif + + if (!dbus_watch_get_enabled(watch)) { + pa_log_warn("Asked to handle disabled watch: %p %i", (void*) watch, fd); + return; + } + + if (events & PA_IO_EVENT_INPUT) + flags |= DBUS_WATCH_READABLE; + if (events & PA_IO_EVENT_OUTPUT) + flags |= DBUS_WATCH_WRITABLE; + if (events & PA_IO_EVENT_HANGUP) + flags |= DBUS_WATCH_HANGUP; + if (events & PA_IO_EVENT_ERROR) + flags |= DBUS_WATCH_ERROR; + + dbus_watch_handle(watch, flags); +} + +/* pa_time_event_cb_t timer event handler */ +static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struct timeval *tv, void *userdata) { + DBusTimeout *timeout = userdata; + + if (dbus_timeout_get_enabled(timeout)) { + struct timeval next = *tv; + dbus_timeout_handle(timeout); + + /* restart it for the next scheduled time */ + pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); + ea->time_restart(e, &next); + } +} + +/* DBusAddWatchFunction callback for pa mainloop */ +static dbus_bool_t add_watch(DBusWatch *watch, void *data) { + pa_dbus_wrap_connection *c = data; + pa_io_event *ev; + + pa_assert(watch); + pa_assert(c); + + ev = c->mainloop->io_new( + c->mainloop, +#if HAVE_DBUS_WATCH_GET_UNIX_FD + dbus_watch_get_unix_fd(watch), +#else + dbus_watch_get_fd(watch), +#endif + get_watch_flags(watch), handle_io_event, watch); + + dbus_watch_set_data(watch, ev, NULL); + + return TRUE; +} + +/* DBusRemoveWatchFunction callback for pa mainloop */ +static void remove_watch(DBusWatch *watch, void *data) { + pa_dbus_wrap_connection *c = data; + pa_io_event *ev; + + pa_assert(watch); + pa_assert(c); + + if ((ev = dbus_watch_get_data(watch))) + c->mainloop->io_free(ev); +} + +/* DBusWatchToggledFunction callback for pa mainloop */ +static void toggle_watch(DBusWatch *watch, void *data) { + pa_dbus_wrap_connection *c = data; + pa_io_event *ev; + + pa_assert(watch); + pa_assert(c); + + pa_assert_se(ev = dbus_watch_get_data(watch)); + + /* get_watch_flags() checks if the watch is enabled */ + c->mainloop->io_enable(ev, get_watch_flags(watch)); +} + +/* DBusAddTimeoutFunction callback for pa mainloop */ +static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { + pa_dbus_wrap_connection *c = data; + pa_time_event *ev; + struct timeval tv; + + pa_assert(timeout); + pa_assert(c); + + if (!dbus_timeout_get_enabled(timeout)) + return FALSE; + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); + + ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout); + + dbus_timeout_set_data(timeout, ev, NULL); + + return TRUE; +} + +/* DBusRemoveTimeoutFunction callback for pa mainloop */ +static void remove_timeout(DBusTimeout *timeout, void *data) { + pa_dbus_wrap_connection *c = data; + pa_time_event *ev; + + pa_assert(timeout); + pa_assert(c); + + if ((ev = dbus_timeout_get_data(timeout))) + c->mainloop->time_free(ev); +} + +/* DBusTimeoutToggledFunction callback for pa mainloop */ +static void toggle_timeout(DBusTimeout *timeout, void *data) { + pa_dbus_wrap_connection *c = data; + pa_time_event *ev; + + pa_assert(timeout); + pa_assert(c); + + pa_assert_se(ev = dbus_timeout_get_data(timeout)); + + if (dbus_timeout_get_enabled(timeout)) { + struct timeval tv; + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); + + c->mainloop->time_restart(ev, &tv); + } else + c->mainloop->time_restart(ev, NULL); +} + +static void wakeup_main(void *userdata) { + pa_dbus_wrap_connection *c = userdata; + + pa_assert(c); + + /* this will wakeup the mainloop and dispatch events, although + * it may not be the cleanest way of accomplishing it */ + c->mainloop->defer_enable(c->dispatch_event, 1); +} + +pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, DBusBusType type, DBusError *error) { + DBusConnection *conn; + pa_dbus_wrap_connection *pconn = NULL; + + pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER); + + if (!(conn = dbus_bus_get_private(type, error))) + return NULL; + + pconn = pa_xnew(pa_dbus_wrap_connection, 1); + pconn->mainloop = m; + pconn->connection = conn; + + dbus_connection_set_exit_on_disconnect(conn, FALSE); + dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL); + dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, pconn, NULL); + dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, pconn, NULL); + dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL); + + pconn->dispatch_event = pconn->mainloop->defer_new(pconn->mainloop, dispatch_cb, conn); + + return pconn; +} + +void pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* c) { + pa_assert(c); + + if (dbus_connection_get_is_connected(c->connection)) { + dbus_connection_close(c->connection); + /* must process remaining messages, bit of a kludge to handle + * both unload and shutdown */ + while (dbus_connection_read_write_dispatch(c->connection, -1)); + } + + c->mainloop->defer_free(c->dispatch_event); + dbus_connection_unref(c->connection); + pa_xfree(c); +} + +DBusConnection* pa_dbus_wrap_connection_get(pa_dbus_wrap_connection *c) { + pa_assert(c); + pa_assert(c->connection); + + return c->connection; +} + +int pa_dbus_add_matches(DBusConnection *c, DBusError *error, ...) { + const char *t; + va_list ap; + unsigned k = 0; + + pa_assert(c); + pa_assert(error); + + va_start(ap, error); + while ((t = va_arg(ap, const char*))) { + dbus_bus_add_match(c, t, error); + + if (dbus_error_is_set(error)) + goto fail; + + k++; + } + va_end(ap); + return 0; + +fail: + + va_end(ap); + va_start(ap, error); + for (; k > 0; k--) { + DBusError e; + + pa_assert_se(t = va_arg(ap, const char*)); + + dbus_error_init(&e); + dbus_bus_remove_match(c, t, &e); + dbus_error_free(&e); + } + va_end(ap); + + return -1; +} + +void pa_dbus_remove_matches(DBusConnection *c, ...) { + const char *t; + va_list ap; + DBusError error; + + pa_assert(c); + + dbus_error_init(&error); + + va_start(ap, c); + while ((t = va_arg(ap, const char*))) { + dbus_bus_remove_match(c, t, &error); + dbus_error_free(&error); + } + va_end(ap); +} + +pa_dbus_pending *pa_dbus_pending_new( + DBusConnection *c, + DBusMessage *m, + DBusPendingCall *pending, + void *context_data, + void *call_data) { + + pa_dbus_pending *p; + + pa_assert(pending); + + p = pa_xnew(pa_dbus_pending, 1); + p->connection = c; + p->message = m; + p->pending = pending; + p->context_data = context_data; + p->call_data = call_data; + + PA_LLIST_INIT(pa_dbus_pending, p); + + return p; +} + +void pa_dbus_pending_free(pa_dbus_pending *p) { + pa_assert(p); + + if (p->pending) + dbus_pending_call_cancel(p->pending); /* p->pending is freed by cancel() */ + + if (p->message) + dbus_message_unref(p->message); + + pa_xfree(p); +} + +void pa_dbus_sync_pending_list(pa_dbus_pending **p) { + pa_assert(p); + + while (*p && dbus_connection_read_write_dispatch((*p)->connection, -1)) + ; +} + +void pa_dbus_free_pending_list(pa_dbus_pending **p) { + pa_dbus_pending *i; + + pa_assert(p); + + while ((i = *p)) { + PA_LLIST_REMOVE(pa_dbus_pending, *p, i); + pa_dbus_pending_free(i); + } +} diff --git a/src/pulsecore/dbus-util.h b/src/pulsecore/dbus-util.h new file mode 100644 index 00000000..55cda7a0 --- /dev/null +++ b/src/pulsecore/dbus-util.h @@ -0,0 +1,63 @@ +#ifndef foodbusutilhfoo +#define foodbusutilhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2006 Shams E. King + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include +#include + +/* A wrap connection is not shared or refcounted, it is available in client side */ +typedef struct pa_dbus_wrap_connection pa_dbus_wrap_connection; + +pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *mainloop, DBusBusType type, DBusError *error); +void pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* conn); + +DBusConnection* pa_dbus_wrap_connection_get(pa_dbus_wrap_connection *conn); + +int pa_dbus_add_matches(DBusConnection *c, DBusError *error, ...) PA_GCC_SENTINEL; +void pa_dbus_remove_matches(DBusConnection *c, ...) PA_GCC_SENTINEL; + +typedef struct pa_dbus_pending pa_dbus_pending; + +struct pa_dbus_pending { + DBusConnection *connection; + DBusMessage *message; + DBusPendingCall *pending; + + void *context_data; + void *call_data; + + PA_LLIST_FIELDS(pa_dbus_pending); +}; + +pa_dbus_pending *pa_dbus_pending_new(DBusConnection *c, DBusMessage *m, DBusPendingCall *pending, void *context_data, void *call_data); +void pa_dbus_pending_free(pa_dbus_pending *p); + +/* Sync up a list of pa_dbus_pending_call objects */ +void pa_dbus_sync_pending_list(pa_dbus_pending **p); + +/* Free up a list of pa_dbus_pending_call objects */ +void pa_dbus_free_pending_list(pa_dbus_pending **p); + +#endif -- cgit From b4ef64d198016816568b7b1285afcffeb6fa8382 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Fri, 20 Mar 2009 18:39:30 +0200 Subject: daemon: take org.pulseaudio --- src/daemon/main.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/daemon/main.c b/src/daemon/main.c index 47ca2673..1d543481 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -87,6 +87,9 @@ #include #include #include +#ifdef HAVE_DBUS +#include +#endif #include "cmdline.h" #include "cpulimit.h" @@ -330,6 +333,31 @@ static void set_all_rlimits(const pa_daemon_conf *conf) { } #endif +#ifdef HAVE_DBUS +static void register_org_pulseaudio(pa_core *c) +{ + DBusError error; + pa_dbus_connection *conn; + + dbus_error_init(&error); + if (!(conn = pa_dbus_bus_get(c, pa_in_system_mode() ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { + pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message); + goto finish_dbus; + } + + if (dbus_bus_request_name (pa_dbus_connection_get(conn), "org.pulseaudio", 0, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) + pa_log_debug("Got org.pulseaudio!"); + else if (dbus_error_is_set(&error)) + pa_log_warn("Unable to get org.pulseaudio: %s: %s", error.name, error.message); + +finish_dbus: + if (conn) + pa_dbus_connection_unref(conn); + + dbus_error_free(&error); +} +#endif + int main(int argc, char *argv[]) { pa_core *c = NULL; pa_strbuf *buf = NULL; @@ -997,6 +1025,10 @@ int main(int argc, char *argv[]) { } #endif +#ifdef HAVE_DBUS + register_org_pulseaudio(c); +#endif + pa_log_info(_("Daemon startup complete.")); retval = 0; -- cgit From 1dad83b73c625a8576466b63bb80d666394d9b93 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Fri, 20 Mar 2009 16:51:28 +0200 Subject: pulse: client connect to dbus --- src/pulse/context.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/pulse/context.h | 7 +++-- src/pulse/def.h | 5 +++- src/pulse/internal.h | 5 ++++ 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index 00dffc25..a18a6423 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -102,6 +102,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event }; static void context_free(pa_context *c); +static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata); pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { return pa_context_new_with_proplist(mainloop, name, NULL); @@ -141,6 +142,8 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char * if (name) pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name); + c->no_fail = FALSE; + c->system_bus = c->session_bus = NULL; c->mainloop = mainloop; c->client = NULL; c->pstream = NULL; @@ -235,6 +238,16 @@ static void context_free(pa_context *c) { context_unlink(c); + if (c->system_bus) { + dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->system_bus), filter_cb, c); + pa_dbus_wrap_connection_free(c->system_bus); + } + + if (c->session_bus) { + dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->session_bus), filter_cb, c); + pa_dbus_wrap_connection_free(c->session_bus); + } + if (c->record_streams) pa_dynarray_free(c->record_streams, NULL, NULL); if (c->playback_streams) @@ -726,6 +739,32 @@ fail: static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata); +static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wrap_connection **conn) { + DBusError error; + + pa_assert(c); + pa_assert(conn); + + dbus_error_init(&error); + if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, type, &error)) || dbus_error_is_set(&error)) { + pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message); + goto finish; + } + + if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn), filter_cb, c, NULL)) { + pa_log_warn("Failed to add filter function"); + goto finish; + } + + if (pa_dbus_add_matches( + pa_dbus_wrap_connection_get(*conn), &error, + "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio',arg1=''", NULL) < 0) + pa_log_warn("Unable to track org.pulseaudio: %s: %s", error.name, error.message); + + finish: + dbus_error_free(&error); +} + static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; @@ -758,7 +797,14 @@ static int try_next_connection(pa_context *c) { } #endif - pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); + if (c->no_fail) { + if (!c->system_bus) + track_pulseaudio_on_dbus(c, DBUS_BUS_SYSTEM, &c->system_bus); + if (!c->session_bus) + track_pulseaudio_on_dbus(c, DBUS_BUS_SESSION, &c->session_bus); + } else + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); + goto finish; } @@ -815,6 +861,34 @@ finish: pa_context_unref(c); } +static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) { + pa_context *c = userdata; + pa_bool_t is_session; + + pa_assert(bus); + pa_assert(message); + pa_assert(c); + + if (c->state != PA_CONTEXT_CONNECTING) + goto finish; + + is_session = bus == pa_dbus_wrap_connection_get(c->session_bus); + pa_log_debug("Rock!! PulseAudio is baack on %s bus", is_session ? "session" : "system"); + + if (is_session) { + /* The user instance via PF_LOCAL */ + c->server_list = prepend_per_user(c->server_list); + } else { + /* The system wide instance via PF_LOCAL */ + c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET); + } + + try_next_connection(c); + +finish: + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + int pa_context_connect( pa_context *c, const char *server, @@ -828,7 +902,7 @@ int pa_context_connect( PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED); PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID); + PA_CHECK_VALIDITY(c, !(flags & ~(PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL)), PA_ERR_INVALID); PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID); if (!server) @@ -836,6 +910,7 @@ int pa_context_connect( pa_context_ref(c); + c->no_fail = flags & PA_CONTEXT_NOFAIL; pa_assert(!c->server_list); if (server) { diff --git a/src/pulse/context.h b/src/pulse/context.h index c32cf443..139d0e0b 100644 --- a/src/pulse/context.h +++ b/src/pulse/context.h @@ -207,9 +207,10 @@ pa_context_state_t pa_context_get_state(pa_context *c); connect to the default server. This routine may but will not always return synchronously on error. Use pa_context_set_state_callback() to be notified when the connection is established. If flags doesn't have -PA_NOAUTOSPAWN set and no specific server is specified or accessible a -new daemon is spawned. If api is non-NULL, the functions specified in -the structure are used when forking a new child process. */ +PA_CONTEXT_NOAUTOSPAWN set and no specific server is specified or +accessible a new daemon is spawned. If api is non-NULL, the functions +specified in the structure are used when forking a new child +process. */ int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api); /** Terminate the context connection immediately */ diff --git a/src/pulse/def.h b/src/pulse/def.h index 9418e96f..48b6f3ec 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -109,13 +109,16 @@ typedef enum pa_operation_state { /** Some special flags for contexts. */ typedef enum pa_context_flags { - PA_CONTEXT_NOAUTOSPAWN = 1 + PA_CONTEXT_NOAUTOSPAWN = 0x0001U, /**< Disabled autospawning of the PulseAudio daemon if required */ + PA_CONTEXT_NOFAIL = 0x0002U + /**< Don't fail if the daemon is not available when pa_context_connect() is called, instead enter PA_CONTEXT_CONNECTING state and wait for the daemon to appear. \since 0.9.15 */ } pa_context_flags_t; /** \cond fulldocs */ /* Allow clients to check with #ifdef for those flags */ #define PA_CONTEXT_NOAUTOSPAWN PA_CONTEXT_NOAUTOSPAWN +#define PA_CONTEXT_NOFAIL PA_CONTEXT_NOFAIL /** \endcond */ /** The direction of a pa_stream object */ diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 9646d8a6..88b99ef8 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -42,6 +42,7 @@ #include #include #include +#include #include "client-conf.h" @@ -50,6 +51,10 @@ struct pa_context { PA_REFCNT_DECLARE; + pa_bool_t no_fail:1; + pa_dbus_wrap_connection *system_bus; + pa_dbus_wrap_connection *session_bus; + pa_proplist *proplist; pa_mainloop_api* mainloop; -- cgit From 8491b47a5164fdff10724bfe74411791dc0ff912 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Fri, 27 Mar 2009 20:41:52 +0200 Subject: gtk-test: updated to use PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL --- src/tests/gtk-test.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/tests/gtk-test.c b/src/tests/gtk-test.c index f82aca58..6470e484 100644 --- a/src/tests/gtk-test.c +++ b/src/tests/gtk-test.c @@ -29,12 +29,38 @@ #include #include +pa_context *ctxt; +pa_glib_mainloop *m; + +static void context_state_callback(pa_context *c, void *userdata); + +static void connect(void) { + int r; + + ctxt = pa_context_new(pa_glib_mainloop_get_api(m), NULL); + g_assert(ctxt); + + r = pa_context_connect(ctxt, NULL, PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL, NULL); + g_assert(r == 0); + + pa_context_set_state_callback(ctxt, context_state_callback, NULL); +} + +static void context_state_callback(pa_context *c, void *userdata) { + switch (pa_context_get_state(c)) { + case PA_CONTEXT_FAILED: + pa_context_unref(ctxt); + ctxt = NULL; + connect(); + break; + default: + break; + } +} + int main(int argc, char *argv[]) { - pa_context *c; - pa_glib_mainloop *m; GtkWidget *window; - int r; gtk_init(&argc, &argv); @@ -49,15 +75,10 @@ int main(int argc, char *argv[]) { m = pa_glib_mainloop_new(NULL); g_assert(m); - c = pa_context_new(pa_glib_mainloop_get_api(m), NULL); - g_assert(c); - - r = pa_context_connect(c, NULL, 0, NULL); - g_assert(r == 0); - + connect(); gtk_main(); - pa_context_unref(c); + pa_context_unref(ctxt); pa_glib_mainloop_free(m); return 0; -- cgit