mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
daemon: Implement the DBus server lookup service.
This commit is contained in:
parent
c94e7421aa
commit
5babbaafb2
10 changed files with 490 additions and 37 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,35 +1052,48 @@ 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);
|
||||
|
||||
pa_log_error("%s", s = pa_strbuf_tostring_free(buf));
|
||||
pa_xfree(s);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
||||
/* 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 (!c->modules || pa_idxset_size(c->modules) == 0) {
|
||||
pa_log(_("Daemon startup without any loaded modules, refusing to work."));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
if (daemon_pipe[1] >= 0) {
|
||||
int ok = 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) {
|
||||
|
|
|
|||
277
src/daemon/server-lookup.c
Normal file
277
src/daemon/server-lookup.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
42
src/daemon/server-lookup.h
Normal file
42
src/daemon/server-lookup.h
Normal file
|
|
@ -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
|
||||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
; default-sink =
|
||||
; default-source =
|
||||
; default-server =
|
||||
; default-dbus-server =
|
||||
|
||||
; autospawn = yes
|
||||
; daemon-binary = @PA_BINARY@
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue