Index: src/pulsecore/auth-cookie.c =================================================================== --- src/pulsecore/auth-cookie.c (revision 25849) +++ src/pulsecore/auth-cookie.c (working copy) @@ -77,6 +77,41 @@ return c; } +pa_auth_cookie* pa_auth_cookie_create(pa_core *core, const void *data, size_t size) +{ + pa_auth_cookie *c; + char *t; + + pa_assert(core); + pa_assert(data); + pa_assert(size > 0); + + t = pa_xstrdup("auth-cookie"); + + if ((c = pa_shared_get(core, t))) { + + pa_xfree(t); + + if (c->size != size) + return NULL; + + return pa_auth_cookie_ref(c); + } + + c = pa_xmalloc(PA_ALIGN(sizeof(pa_auth_cookie)) + size); + PA_REFCNT_INIT(c); + c->core = core; + c->name = t; + c->size = size; + + pa_assert_se(pa_shared_set(core, t, c) >= 0); + + memcpy((uint8_t*) c + PA_ALIGN(sizeof(pa_auth_cookie)), data, size); + + return c; +} + + pa_auth_cookie* pa_auth_cookie_ref(pa_auth_cookie *c) { pa_assert(c); pa_assert(PA_REFCNT_VALUE(c) >= 1); Index: src/pulsecore/auth-cookie.h =================================================================== --- src/pulsecore/auth-cookie.h (revision 25849) +++ src/pulsecore/auth-cookie.h (working copy) @@ -27,6 +27,7 @@ typedef struct pa_auth_cookie pa_auth_cookie; pa_auth_cookie* pa_auth_cookie_get(pa_core *c, const char *cn, size_t size); +pa_auth_cookie* pa_auth_cookie_create(pa_core *c, const void *data, size_t size); pa_auth_cookie* pa_auth_cookie_ref(pa_auth_cookie *c); void pa_auth_cookie_unref(pa_auth_cookie *c); Index: src/modules/module-tunnel.c =================================================================== --- src/modules/module-tunnel.c (revision 25849) +++ src/modules/module-tunnel.c (working copy) @@ -31,6 +31,10 @@ #include #include +#ifdef HAVE_X11 +#include +#endif + #include #include #include @@ -61,6 +65,11 @@ #include "module-tunnel-source-symdef.h" #endif +#define ENV_DEFAULT_SINK "PULSE_SINK" +#define ENV_DEFAULT_SOURCE "PULSE_SOURCE" +#define ENV_DEFAULT_SERVER "PULSE_SERVER" +#define ENV_COOKIE_FILE "PULSE_COOKIE" + #ifdef TUNNEL_SINK PA_MODULE_DESCRIPTION("Tunnel module for sinks"); PA_MODULE_USAGE( @@ -1929,6 +1938,10 @@ #else pa_source_new_data data; #endif +#ifdef HAVE_X11 + xcb_connection_t *xcb = NULL; +#endif + const char *cookie_path; pa_assert(m); @@ -1945,11 +1958,9 @@ u->pstream = NULL; u->server_name = NULL; #ifdef TUNNEL_SINK - u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));; u->sink = NULL; u->requested_bytes = 0; #else - u->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));; u->source = NULL; #endif u->smoother = pa_smoother_new( @@ -1971,14 +1982,99 @@ u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); - if (!(u->auth_cookie = pa_auth_cookie_get(u->core, pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), PA_NATIVE_COOKIE_LENGTH))) - goto fail; +#ifdef HAVE_X11 + /* Need an X11 connection to get root properties */ + if (getenv("DISPLAY") != NULL) { + if (!(xcb = xcb_connect(getenv("DISPLAY"), NULL))) + pa_log("xcb_connect() failed"); + else { + if (xcb_connection_has_error(xcb)) { + pa_log("xcb_connection_has_error() returned true"); + xcb_disconnect(xcb); + xcb = NULL; + } + } + } +#endif - if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) { + /* Figure out the cookie the same way a normal client would */ + cookie_path = pa_modargs_get_value(ma, "cookie", NULL); + + if (cookie_path == NULL) + cookie_path = getenv(ENV_COOKIE_FILE); + +#ifdef HAVE_X11 + if ((cookie_path == NULL) && (xcb != NULL)) { + char t[1024]; + if (pa_x11_get_prop(xcb, 0, "PULSE_COOKIE", t, sizeof(t))) { + uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; + + if (pa_parsehex(t, cookie, sizeof(cookie)) != sizeof(cookie)) + pa_log("Failed to parse cookie data"); + else { + if (!(u->auth_cookie = pa_auth_cookie_create(u->core, cookie, sizeof(cookie)))) + goto fail; + } + } + } +#endif + + if ((cookie_path == NULL) && (u->auth_cookie == NULL)) + cookie_path = PA_NATIVE_COOKIE_FILE; + + if (cookie_path != NULL) { + if (!(u->auth_cookie = pa_auth_cookie_get(u->core, cookie_path, PA_NATIVE_COOKIE_LENGTH))) + goto fail; + } + + /* Same thing for the server name */ + u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)); + + if (u->server_name == NULL) + u->server_name = pa_xstrdup(getenv(ENV_DEFAULT_SERVER)); + +#ifdef HAVE_X11 + if ((u->server_name == NULL) && (xcb != NULL)) { + char t[1024]; + if (pa_x11_get_prop(xcb, 0, "PULSE_SERVER", t, sizeof(t))) + u->server_name = pa_xstrdup(t); + } +#endif + + if (u->server_name == NULL) { pa_log("No server specified."); goto fail; } + /* Also determine the default sink/source on the other server */ +#ifdef TUNNEL_SINK + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));; + + if (u->sink_name == NULL) + u->sink_name = pa_xstrdup(getenv(ENV_DEFAULT_SINK)); + +#ifdef HAVE_X11 + if ((u->sink_name == NULL) && (xcb != NULL)) { + char t[1024]; + if (pa_x11_get_prop(xcb, 0, "PULSE_SINK", t, sizeof(t))) + u->sink_name = pa_xstrdup(t); + } +#endif +#else + u->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));; + + if (u->source_name == NULL) + u->source_name = pa_xstrdup(getenv(ENV_DEFAULT_SOURCE)); + +#ifdef HAVE_X11 + if ((u->source_name == NULL) && (xcb != NULL)) { + char t[1024]; + if (pa_x11_get_prop(xcb, 0, "PULSE_SOURCE", t, sizeof(t))) + u->source_name = pa_xstrdup(t); + } +#endif +#endif + ss = m->core->default_sample_spec; map = m->core->default_channel_map; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { @@ -2001,7 +2097,7 @@ pa_sink_new_data_init(&data); data.driver = __FILE__; data.module = m; - data.namereg_fail = TRUE; + data.namereg_fail = FALSE; pa_sink_new_data_set_name(&data, dn); pa_sink_new_data_set_sample_spec(&data, &ss); pa_sink_new_data_set_channel_map(&data, &map); @@ -2045,7 +2141,7 @@ pa_source_new_data_init(&data); data.driver = __FILE__; data.module = m; - data.namereg_fail = TRUE; + data.namereg_fail = FALSE; pa_source_new_data_set_name(&data, dn); pa_source_new_data_set_sample_spec(&data, &ss); pa_source_new_data_set_channel_map(&data, &map); @@ -2102,6 +2198,11 @@ pa_source_put(u->source); #endif +#ifdef HAVE_X11 + if (xcb) + xcb_disconnect(xcb); +#endif + pa_modargs_free(ma); return 0; @@ -2109,6 +2210,11 @@ fail: pa__done(m); +#ifdef HAVE_X11 + if (xcb) + xcb_disconnect(xcb); +#endif + if (ma) pa_modargs_free(ma);