diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 5 | ||||
| -rw-r--r-- | src/daemon/daemon-conf.c | 48 | ||||
| -rw-r--r-- | src/daemon/daemon-conf.h | 9 | ||||
| -rw-r--r-- | src/daemon/daemon.conf.in | 1 | ||||
| -rw-r--r-- | src/daemon/main.c | 136 | ||||
| -rw-r--r-- | src/daemon/server-lookup.c | 277 | ||||
| -rw-r--r-- | src/daemon/server-lookup.h | 42 | ||||
| -rw-r--r-- | src/pulse/client-conf.c | 3 | ||||
| -rw-r--r-- | src/pulse/client-conf.h | 3 | ||||
| -rw-r--r-- | src/pulse/client.conf.in | 1 | 
10 files changed, 489 insertions, 36 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 70b16be3..c56f7608 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -135,13 +135,14 @@ BUILT_SOURCES = \  bin_PROGRAMS = pulseaudio  pulseaudio_SOURCES = \ -		daemon/caps.h daemon/caps.c \ +		daemon/caps.c daemon/caps.h \  		daemon/cmdline.c daemon/cmdline.h \  		daemon/cpulimit.c daemon/cpulimit.h \  		daemon/daemon-conf.c daemon/daemon-conf.h \  		daemon/dumpmodules.c daemon/dumpmodules.h \  		daemon/ltdl-bind-now.c daemon/ltdl-bind-now.h \ -		daemon/main.c +		daemon/main.c \ +		daemon/server-lookup.c daemon/server-lookup.h  pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(LIBOIL_CFLAGS) $(DBUS_CFLAGS)  pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS) $(DBUS_LIBS) diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index ac6cc8aa..e6fa8c64 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -83,6 +83,9 @@ static const pa_daemon_conf default_conf = {      .config_file = NULL,      .use_pid_file = TRUE,      .system_instance = FALSE, +#ifdef HAVE_DBUS +    .local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */ +#endif      .no_cpu_limit = FALSE,      .disable_shm = FALSE,      .default_n_fragments = 4, @@ -203,6 +206,22 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {      return 0;  } +int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string) { +    pa_assert(c); +    pa_assert(string); + +    if (!strcmp(string, "user")) +        c->local_server_type = PA_SERVER_TYPE_USER; +    else if (!strcmp(string, "system")) { +        c->local_server_type = PA_SERVER_TYPE_SYSTEM; +    } else if (!strcmp(string, "none")) { +        c->local_server_type = PA_SERVER_TYPE_NONE; +    } else +        return -1; + +    return 0; +} +  static int parse_log_target(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {      pa_daemon_conf *c = data; @@ -430,6 +449,22 @@ static int parse_rtprio(const char *filename, unsigned line, const char *section      return 0;  } +static int parse_server_type(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { +    pa_daemon_conf *c = data; + +    pa_assert(filename); +    pa_assert(lvalue); +    pa_assert(rvalue); +    pa_assert(data); + +    if (pa_daemon_conf_set_local_server_type(c, rvalue) < 0) { +        pa_log(_("[%s:%u] Invalid server type '%s'."), filename, line, rvalue); +        return -1; +    } + +    return 0; +} +  int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {      int r = -1;      FILE *f = NULL; @@ -443,6 +478,9 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {          { "disallow-exit",              pa_config_parse_bool,     &c->disallow_exit, NULL },          { "use-pid-file",               pa_config_parse_bool,     &c->use_pid_file, NULL },          { "system-instance",            pa_config_parse_bool,     &c->system_instance, NULL }, +#ifdef HAVE_DBUS +        { "local-server-type",          parse_server_type,        c, NULL }, +#endif          { "no-cpu-limit",               pa_config_parse_bool,     &c->no_cpu_limit, NULL },          { "disable-shm",                pa_config_parse_bool,     &c->disable_shm, NULL },          { "flat-volumes",               pa_config_parse_bool,     &c->flat_volumes, NULL }, @@ -604,6 +642,13 @@ static const char* const log_level_to_string[] = {      [PA_LOG_ERROR] = "error"  }; +static const char* const server_type_to_string[] = { +    [PA_SERVER_TYPE_UNSET] = "!!UNSET!!", +    [PA_SERVER_TYPE_USER] = "user", +    [PA_SERVER_TYPE_SYSTEM] = "system", +    [PA_SERVER_TYPE_NONE] = "none" +}; +  char *pa_daemon_conf_dump(pa_daemon_conf *c) {      pa_strbuf *s;      char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; @@ -627,6 +672,9 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {      pa_strbuf_printf(s, "disallow-exit = %s\n", pa_yes_no(c->disallow_exit));      pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file));      pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); +#ifdef HAVE_DBUS +    pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]); +#endif      pa_strbuf_printf(s, "no-cpu-limit = %s\n", pa_yes_no(c->no_cpu_limit));      pa_strbuf_printf(s, "disable-shm = %s\n", pa_yes_no(c->disable_shm));      pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes)); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 9cec189f..98db8641 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -48,6 +48,13 @@ typedef enum pa_daemon_conf_cmd {      PA_CMD_CLEANUP_SHM  } pa_daemon_conf_cmd_t; +typedef enum pa_daemon_conf_server_type { +    PA_SERVER_TYPE_UNSET, +    PA_SERVER_TYPE_USER, +    PA_SERVER_TYPE_SYSTEM, +    PA_SERVER_TYPE_NONE +} pa_daemon_conf_server_type_t; +  #ifdef HAVE_SYS_RESOURCE_H  typedef struct pa_rlimit {      rlim_t value; @@ -74,6 +81,7 @@ typedef struct pa_daemon_conf {          log_meta,          log_time,          flat_volumes; +    pa_daemon_conf_server_type_t local_server_type;      int exit_idle_time,          scache_idle_time,          auto_log_target, @@ -151,6 +159,7 @@ int pa_daemon_conf_env(pa_daemon_conf *c);  int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string);  int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string);  int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string); +int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string);  const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c);  FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c); diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index fcd2513a..ecdb3a64 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -25,6 +25,7 @@  ; disallow-exit = no  ; use-pid-file = yes  ; system-instance = no +; local-server-type = user  ; disable-shm = no  ; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB diff --git a/src/daemon/main.c b/src/daemon/main.c index 3e50baad..1b6ed793 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -99,6 +99,7 @@  #include "caps.h"  #include "ltdl-bind-now.h"  #include "polkit.h" +#include "server-lookup.h"  #ifdef HAVE_LIBWRAP  /* Only one instance of these variables */ @@ -335,33 +336,31 @@ static void set_all_rlimits(const pa_daemon_conf *conf) {  #endif  #ifdef HAVE_DBUS -static pa_dbus_connection *register_dbus(pa_core *c) { +static pa_dbus_connection *register_dbus_name(pa_core *c, DBusBusType bus, const char* name) {      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)) { +    if (!(conn = pa_dbus_bus_get(c, bus, &error)) || dbus_error_is_set(&error)) {          pa_log_warn("Unable to contact D-Bus: %s: %s", error.name, error.message);          goto fail;      } -    if (dbus_bus_request_name(pa_dbus_connection_get(conn), "org.pulseaudio.Server", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { -        pa_log_debug("Got org.pulseaudio.Server!"); +    if (dbus_bus_request_name(pa_dbus_connection_get(conn), name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { +        pa_log_debug("Got %s!", name);          return conn;      }      if (dbus_error_is_set(&error)) -        pa_log_warn("Failed to acquire org.pulseaudio.Server: %s: %s", error.name, error.message); +        pa_log_error("Failed to acquire %s: %s: %s", name, error.name, error.message);      else -        pa_log_warn("D-Bus name org.pulseaudio.Server already taken. Weird shit!"); +        pa_log_error("D-Bus name %s already taken. Weird shit!", name);      /* PA cannot be started twice by the same user and hence we can -     * ignore mostly the case that org.pulseaudio.Server is already -     * taken. */ +     * ignore mostly the case that a name is already taken. */  fail: -      if (conn)          pa_dbus_connection_unref(conn); @@ -393,7 +392,10 @@ int main(int argc, char *argv[]) {      int autospawn_fd = -1;      pa_bool_t autospawn_locked = FALSE;  #ifdef HAVE_DBUS -    pa_dbus_connection *dbus = NULL; +    pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */ +    pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */ +    pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */ +    pa_bool_t start_server;  #endif      pa_log_set_ident("pulseaudio"); @@ -486,8 +488,45 @@ int main(int argc, char *argv[]) {          pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);      pa_log_set_show_backtrace(conf->log_backtrace); +#ifdef HAVE_DBUS +    /* conf->system_instance and conf->local_server_type control almost the +     * same thing; make them agree about what is requested. */ +    switch (conf->local_server_type) { +        case PA_SERVER_TYPE_UNSET: +            conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER; +            break; +        case PA_SERVER_TYPE_USER: +        case PA_SERVER_TYPE_NONE: +            conf->system_instance = FALSE; +            break; +        case PA_SERVER_TYPE_SYSTEM: +            conf->system_instance = TRUE; +            break; +        default: +            pa_assert_not_reached(); +    } + +    start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (real_root && conf->local_server_type == PA_SERVER_TYPE_SYSTEM); + +    if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) { +        pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service.")); +        conf->system_instance = FALSE; +    } +#endif +      pa_log_debug("Started as real root: %s, suid root: %s", pa_yes_no(real_root), pa_yes_no(suid_root)); +#ifdef HAVE_DBUS +    /* XXX: Uhh, goto programming... as if this wasn't hard enough to follow +     * already. But if we won't start the full server, we want to just skip all +     * the capability stuff. */ +    if (!start_server) { +        if (!real_root && pa_have_caps()) +            pa_drop_caps(); +        goto after_caps_setup; +    } +#endif +      if (!real_root && pa_have_caps()) {  #ifdef HAVE_SYS_RESOURCE_H          struct rlimit rl; @@ -628,6 +667,10 @@ int main(int argc, char *argv[]) {          conf->realtime_scheduling = FALSE;      } +#ifdef HAVE_DBUS +after_caps_setup: +#endif +      pa_log_debug("Can realtime: %s, can high-priority: %s", pa_yes_no(pa_can_realtime()), pa_yes_no(pa_can_high_priority()));      LTDL_SET_PRELOADED_SYMBOLS(); @@ -716,10 +759,12 @@ int main(int argc, char *argv[]) {      if (real_root && !conf->system_instance)          pa_log_warn(_("This program is not intended to be run as root (unless --system is specified).")); +#ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */      else if (!real_root && conf->system_instance) {          pa_log(_("Root privileges required."));          goto finish;      } +#endif      if (conf->cmd == PA_CMD_START && conf->system_instance) {          pa_log(_("--start not supported for system instances.")); @@ -1007,34 +1052,47 @@ int main(int argc, char *argv[]) {          pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);      buf = pa_strbuf_new(); -    if (conf->load_default_script_file) { -        FILE *f; -        if ((f = pa_daemon_conf_open_default_script_file(conf))) { -            r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); -            fclose(f); +#ifdef HAVE_DBUS +    if (start_server) { +#endif +        if (conf->load_default_script_file) { +            FILE *f; + +            if ((f = pa_daemon_conf_open_default_script_file(conf))) { +                r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); +                fclose(f); +            }          } -    } -    if (r >= 0) -        r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); +        if (r >= 0) +            r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); -    pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); -    pa_xfree(s); +        pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); +        pa_xfree(s); -    /* We completed the initial module loading, so let's disable it -     * from now on, if requested */ -    c->disallow_module_loading = !!conf->disallow_module_loading; +        if (r < 0 && conf->fail) { +            pa_log(_("Failed to initialize daemon.")); +            goto finish; +        } -    if (r < 0 && conf->fail) { -        pa_log(_("Failed to initialize daemon.")); -        goto finish; +        if (!c->modules || pa_idxset_size(c->modules) == 0) { +            pa_log(_("Daemon startup without any loaded modules, refusing to work.")); +            goto finish; +        } +#ifdef HAVE_DBUS +    } else { +        /* When we just provide the D-Bus server lookup service, we don't want +         * any modules to be loaded. We haven't loaded any so far, so one might +         * think there's no way to contact the server, but receiving certain +         * signals could still cause modules to load. */ +        conf->disallow_module_loading = TRUE;      } +#endif -    if (!c->modules || pa_idxset_size(c->modules) == 0) { -        pa_log(_("Daemon startup without any loaded modules, refusing to work.")); -        goto finish; -    } +    /* We completed the initial module loading, so let's disable it +     * from now on, if requested */ +    c->disallow_module_loading = !!conf->disallow_module_loading;  #ifdef HAVE_FORK      if (daemon_pipe[1] >= 0) { @@ -1046,7 +1104,15 @@ int main(int argc, char *argv[]) {  #endif  #ifdef HAVE_DBUS -    dbus = register_dbus(c); +    if (!conf->system_instance) { +        if (!(server_lookup = pa_dbusobj_server_lookup_new(c, conf->local_server_type))) +            goto finish; +        if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.pulseaudio.PulseAudio"))) +            goto finish; +    } + +    if (start_server && !(server_bus = register_dbus_name(c, conf->system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, "org.pulseaudio.Server"))) +        goto finish;  #endif      pa_log_info(_("Daemon startup complete.")); @@ -1059,8 +1125,12 @@ int main(int argc, char *argv[]) {  finish:  #ifdef HAVE_DBUS -    if (dbus) -        pa_dbus_connection_unref(dbus); +    if (server_bus) +        pa_dbus_connection_unref(server_bus); +    if (lookup_service_bus) +        pa_dbus_connection_unref(lookup_service_bus); +    if (server_lookup) +        pa_dbusobj_server_lookup_free(server_lookup);  #endif      if (autospawn_fd >= 0) { diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c new file mode 100644 index 00000000..867c3a1c --- /dev/null +++ b/src/daemon/server-lookup.c @@ -0,0 +1,277 @@ +/*** +  This file is part of PulseAudio. + +  Copyright 2009 Tanu Kaskinen + +  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 <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulse/client-conf.h> +#include <pulse/xmalloc.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-shared.h> +#include <pulsecore/macro.h> + +#include "server-lookup.h" + +struct pa_dbusobj_server_lookup { +    pa_dbus_connection *conn; +    pa_bool_t path_registered; +    pa_daemon_conf_server_type_t server_type; +}; + +static const char introspection[] = +    DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE +    "<node>" +    " <!-- If you are looking for documentation make sure to check out\n" +    "      http://pulseaudio.org/wiki/DBusInterface -->\n" +    " <interface name=\"org.pulseaudio.ServerLookup\">" +    "  <method name=\"GetDBusServers\">" +    "   <arg name=\"result\" type=\"s\" direction=\"out\"/>" +    "  </method>" +    " </interface>" +    " <interface name=\"org.freedesktop.DBus.Introspectable\">" +    "  <method name=\"Introspect\">" +    "   <arg name=\"data\" type=\"s\" direction=\"out\"/>" +    "  </method>" +    " </interface>" +    "</node>"; + +static void unregister_cb(DBusConnection *conn, void *user_data) { +    pa_dbusobj_server_lookup *sl = user_data; + +    pa_assert(sl); +    pa_assert(sl->path_registered); + +    sl->path_registered = FALSE; +} + +static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { +    const char *i = introspection; +    DBusMessage *reply = NULL; + +    pa_assert(conn); +    pa_assert(msg); + +    if (!(reply = dbus_message_new_method_return(msg))) +        goto fail; + +    if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &i, DBUS_TYPE_INVALID)) +        goto fail; + +    if (!dbus_connection_send(conn, reply, NULL)) +        goto oom; + +    dbus_message_unref(reply); + +    return DBUS_HANDLER_RESULT_HANDLED; + +fail: +    if (reply) +        dbus_message_unref(reply); + +    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +oom: +    if (reply) +        dbus_message_unref(reply); + +    return DBUS_HANDLER_RESULT_NEED_MEMORY; +} + +/* Caller frees the string. */ +static char *get_dbus_server_from_type(pa_daemon_conf_server_type_t server_type) { +    char *server_string = NULL; +    char *runtime_dir = NULL; + +    switch (server_type) { +        case PA_SERVER_TYPE_USER: +            runtime_dir = pa_get_runtime_dir(); + +            if (!runtime_dir) +                return NULL; + +            server_string = pa_sprintf_malloc("unix:path=%s/dbus_socket", runtime_dir); +            break; + +        case PA_SERVER_TYPE_SYSTEM: +            server_string = pa_xstrdup("unix:path=/var/run/pulse/dbus_socket"); +            break; + +        case PA_SERVER_TYPE_NONE: +            server_string = pa_xnew0(char, 1); +            break; + +        default: +            pa_assert_not_reached(); +    } + +    return server_string; +} + +static DBusHandlerResult handle_get_dbus_servers(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { +    DBusMessage *reply = NULL; +    pa_client_conf *conf = NULL; +    char *server_string = NULL; + +    pa_assert(conn); +    pa_assert(msg); +    pa_assert(sl); + +    conf = pa_client_conf_new(); + +    if (pa_client_conf_load(conf, NULL) < 0) { +        if (!(reply = dbus_message_new_error(msg, "org.pulseaudio.ClientConfLoadError", "Failed to load client.conf."))) +            goto fail; +        if (!dbus_connection_send(conn, reply, NULL)) +            goto oom; +        return DBUS_HANDLER_RESULT_HANDLED; +    } + +    server_string = pa_xstrdup(conf->default_dbus_server); + +    pa_client_conf_free(conf); + +    if (!server_string) { +        if (!(server_string = get_dbus_server_from_type(sl->server_type))) { +            if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "get_dbus_server_from_type() failed."))) +                goto fail; +            if (!dbus_connection_send(conn, reply, NULL)) +                goto oom; +            return DBUS_HANDLER_RESULT_HANDLED; +        } +    } + +    if (!(reply = dbus_message_new_method_return(msg))) +        goto oom; + +    if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &server_string, DBUS_TYPE_INVALID)) +        goto fail; + +    if (!dbus_connection_send(conn, reply, NULL)) +        goto oom; + +    pa_log("Sent reply with server_string '%s'.", server_string); + +    pa_xfree(server_string); + +    dbus_message_unref(reply); + +    return DBUS_HANDLER_RESULT_HANDLED; + +fail: +    if (conf) +        pa_client_conf_free(conf); + +    pa_xfree(server_string); + +    if (reply) +        dbus_message_unref(reply); + +    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +oom: +    if (conf) +        pa_client_conf_free(conf); + +    pa_xfree(server_string); + +    if (reply) +        dbus_message_unref(reply); + +    return DBUS_HANDLER_RESULT_NEED_MEMORY; +} + +static DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void *user_data) { +    pa_dbusobj_server_lookup *sl = user_data; + +    pa_assert(conn); +    pa_assert(msg); +    pa_assert(sl); + +    /* pa_log("Got message! type = %s   path = %s   iface = %s   member = %s   dest = %s", dbus_message_type_to_string(dbus_message_get_type(msg)), dbus_message_get_path(msg), dbus_message_get_interface(msg), dbus_message_get_member(msg), dbus_message_get_destination(msg)); */ + +    if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) +        return handle_introspect(conn, msg, sl); + +    if (dbus_message_is_method_call(msg, "org.pulseaudio.ServerLookup", "GetDBusServers")) +        return handle_get_dbus_servers(conn, msg, sl); + +    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusObjectPathVTable vtable = { +    .unregister_function = unregister_cb, +    .message_function = message_cb, +    .dbus_internal_pad1 = NULL, +    .dbus_internal_pad2 = NULL, +    .dbus_internal_pad3 = NULL, +    .dbus_internal_pad4 = NULL +}; + +pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c, pa_daemon_conf_server_type_t server_type) { +    pa_dbusobj_server_lookup *sl; +    DBusError error; + +    dbus_error_init(&error); + +    sl = pa_xnew(pa_dbusobj_server_lookup, 1); +    sl->path_registered = FALSE; +    sl->server_type = server_type; + +    if (!(sl->conn = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { +        pa_log("Unable to contact D-Bus: %s: %s", error.name, error.message); +        goto fail; +    } + +    if (!dbus_connection_register_object_path(pa_dbus_connection_get(sl->conn), "/org/pulseaudio/server_lookup", &vtable, sl)) { +        pa_log("dbus_connection_register_object_path() failed for /org/pulseaudio/server_lookup."); +        goto fail; +    } + +    sl->path_registered = TRUE; + +    return sl; + +fail: +    dbus_error_free(&error); + +    pa_dbusobj_server_lookup_free(sl); + +    return NULL; +} + +void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl) { +    pa_assert(sl); + +    if (sl->path_registered) { +        pa_assert(sl->conn); +        if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(sl->conn), "/org/pulseaudio/server_lookup")) +            pa_log_debug("dbus_connection_unregister_object_path() failed for /org/pulseaudio/server_lookup."); +    } + +    if (sl->conn) +        pa_dbus_connection_unref(sl->conn); + +    pa_xfree(sl); +}
\ No newline at end of file diff --git a/src/daemon/server-lookup.h b/src/daemon/server-lookup.h new file mode 100644 index 00000000..69fdacdd --- /dev/null +++ b/src/daemon/server-lookup.h @@ -0,0 +1,42 @@ +#ifndef fooserverlookuphfoo +#define fooserverlookuphfoo + +/*** +  This file is part of PulseAudio. + +  Copyright 2009 Tanu Kaskinen + +  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. +***/ + +/* This object implements the D-Bus object at path + * /org/pulseaudio/server_lookup. Implemented interfaces + * are org.pulseaudio.ServerLookup and org.freedesktop.DBus.Introspectable. + * + * See http://pulseaudio.org/wiki/DBusInterface for the ServerLookup interface + * documentation. + */ + +#include <pulsecore/core.h> + +#include "daemon-conf.h" + +typedef struct pa_dbusobj_server_lookup pa_dbusobj_server_lookup; + +pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c, pa_daemon_conf_server_type_t server_type); +void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl); + +#endif
\ No newline at end of file diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 940d0b67..8eab1094 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -57,6 +57,7 @@ static const pa_client_conf default_conf = {      .default_sink = NULL,      .default_source = NULL,      .default_server = NULL, +    .default_dbus_server = NULL,      .autospawn = TRUE,      .disable_shm = FALSE,      .cookie_file = NULL, @@ -81,6 +82,7 @@ void pa_client_conf_free(pa_client_conf *c) {      pa_xfree(c->default_sink);      pa_xfree(c->default_source);      pa_xfree(c->default_server); +    pa_xfree(c->default_dbus_server);      pa_xfree(c->cookie_file);      pa_xfree(c);  } @@ -97,6 +99,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {          { "default-sink",           pa_config_parse_string,  &c->default_sink, NULL },          { "default-source",         pa_config_parse_string,  &c->default_source, NULL },          { "default-server",         pa_config_parse_string,  &c->default_server, NULL }, +        { "default-dbus-server",    pa_config_parse_string,  &c->default_dbus_server, NULL },          { "autospawn",              pa_config_parse_bool,    &c->autospawn, NULL },          { "cookie-file",            pa_config_parse_string,  &c->cookie_file, NULL },          { "disable-shm",            pa_config_parse_bool,    &c->disable_shm, NULL }, diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index ab97dc6a..618216f4 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -22,12 +22,13 @@    USA.  ***/ +#include <pulsecore/macro.h>  #include <pulsecore/native-common.h>  /* A structure containing configuration data for PulseAudio clients. */  typedef struct pa_client_conf { -    char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; +    char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *default_dbus_server, *cookie_file;      pa_bool_t autospawn, disable_shm;      uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];      pa_bool_t cookie_valid; /* non-zero, when cookie is valid */ diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index 579bcc20..3340b0b2 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -22,6 +22,7 @@  ; default-sink =  ; default-source =  ; default-server = +; default-dbus-server =  ; autospawn = yes  ; daemon-binary = @PA_BINARY@  | 
