[pulseaudio-commits] src/modules src/pulsecore

Tanu Kaskinen tanuk at kemper.freedesktop.org
Fri Sep 13 06:52:30 PDT 2013


 src/modules/module-tunnel.c |  187 +++++++++++++++++++++++++++++++++++++++++---
 src/pulsecore/auth-cookie.c |   33 +++++++
 src/pulsecore/auth-cookie.h |    1 
 3 files changed, 211 insertions(+), 10 deletions(-)

New commits:
commit 23c39bb54041a8774b5184802fc7764376bf0565
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jul 11 13:57:41 2013 +0200

    module-tunnel: automatically find the PulseAudio server
    
    Make the PulseAudio tunnel behave the same way as a client
    when it comes to figuring out how to connect to the current
    PulseAudio daemon. This can be useful if you start a second
    PulseAudio instance for e.g. network access.

diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index ad45f73..1ddfd25 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -31,6 +31,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#ifdef HAVE_X11
+#include <xcb/xcb.h>
+#endif
+
 #include <pulse/rtclock.h>
 #include <pulse/timeval.h>
 #include <pulse/util.h>
@@ -54,6 +58,11 @@
 #include <pulsecore/proplist-util.h>
 #include <pulsecore/auth-cookie.h>
 #include <pulsecore/mcalign.h>
+#include <pulsecore/strlist.h>
+
+#ifdef HAVE_X11
+#include <pulsecore/x11prop.h>
+#endif
 
 #ifdef TUNNEL_SINK
 #include "module-tunnel-sink-symdef.h"
@@ -61,11 +70,17 @@
 #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(
         "sink_name=<name for the local sink> "
         "sink_properties=<properties for the local sink> "
+        "auto=<determine server/sink/cookie automatically> "
         "server=<address> "
         "sink=<remote sink name> "
         "cookie=<filename> "
@@ -78,6 +93,7 @@ PA_MODULE_DESCRIPTION("Tunnel module for sources");
 PA_MODULE_USAGE(
         "source_name=<name for the local source> "
         "source_properties=<properties for the local source> "
+        "auto=<determine server/source/cookie automatically> "
         "server=<address> "
         "source=<remote source name> "
         "cookie=<filename> "
@@ -92,6 +108,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(false);
 
 static const char* const valid_modargs[] = {
+    "auto",
     "server",
     "cookie",
     "format",
@@ -1898,6 +1915,8 @@ static void sink_set_mute(pa_sink *sink) {
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u = NULL;
+    char *server = NULL;
+    pa_strlist *server_list = NULL;
     pa_sample_spec ss;
     pa_channel_map map;
     char *dn = NULL;
@@ -1906,6 +1925,11 @@ int pa__init(pa_module*m) {
 #else
     pa_source_new_data data;
 #endif
+    bool automatic;
+#ifdef HAVE_X11
+    xcb_connection_t *xcb = NULL;
+#endif
+    const char *cookie_path;
 
     pa_assert(m);
 
@@ -1948,12 +1972,119 @@ int pa__init(pa_module*m) {
     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), true, PA_NATIVE_COOKIE_LENGTH)))
+    if (pa_modargs_get_value_boolean(ma, "auto", &automatic) < 0) {
+        pa_log("Failed to parse argument \"auto\".");
         goto fail;
+    }
 
-    if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) {
-        pa_log("No server specified.");
-        goto fail;
+    cookie_path = pa_modargs_get_value(ma, "cookie", NULL);
+    server = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL));
+
+    if (automatic) {
+#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
+
+        /* Figure out the cookie the same way a normal client would */
+        if (cookie_path)
+            cookie_path = getenv(ENV_COOKIE_FILE);
+
+#ifdef HAVE_X11
+        if (!cookie_path && xcb) {
+            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
+
+        /* Same thing for the server name */
+        if (!server)
+            server = pa_xstrdup(getenv(ENV_DEFAULT_SERVER));
+
+#ifdef HAVE_X11
+        if (!server && xcb) {
+            char t[1024];
+            if (pa_x11_get_prop(xcb, 0, "PULSE_SERVER", t, sizeof(t)))
+                server = pa_xstrdup(t);
+        }
+#endif
+
+        /* Also determine the default sink/source on the other server */
+#ifdef TUNNEL_SINK
+        if (!u->sink_name)
+            u->sink_name = pa_xstrdup(getenv(ENV_DEFAULT_SINK));
+
+#ifdef HAVE_X11
+        if (!u->sink_name && xcb) {
+            char t[1024];
+            if (pa_x11_get_prop(xcb, 0, "PULSE_SINK", t, sizeof(t)))
+                u->sink_name = pa_xstrdup(t);
+        }
+#endif
+#else
+        if (!u->source_name)
+            u->source_name = pa_xstrdup(getenv(ENV_DEFAULT_SOURCE));
+
+#ifdef HAVE_X11
+        if (!u->source_name && xcb) {
+            char t[1024];
+            if (pa_x11_get_prop(xcb, 0, "PULSE_SOURCE", t, sizeof(t)))
+                u->source_name = pa_xstrdup(t);
+        }
+#endif
+#endif
+    }
+
+    if (!cookie_path && !u->auth_cookie)
+        cookie_path = PA_NATIVE_COOKIE_FILE;
+
+    if (cookie_path) {
+        if (!(u->auth_cookie = pa_auth_cookie_get(u->core, cookie_path, true, PA_NATIVE_COOKIE_LENGTH)))
+            goto fail;
+    }
+
+    if (server) {
+        if (!(server_list = pa_strlist_parse(server))) {
+            pa_log("Invalid server specified.");
+            goto fail;
+        }
+    } else {
+        char *ufn;
+
+        if (!automatic) {
+            pa_log("No server specified.");
+            goto fail;
+        }
+
+        pa_log("No server address found. Attempting default local sockets.");
+
+        /* The system wide instance via PF_LOCAL */
+        server_list = pa_strlist_prepend(server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
+
+        /* The user instance via PF_LOCAL */
+        if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
+            server_list = pa_strlist_prepend(server_list, ufn);
+            pa_xfree(ufn);
+        }
     }
 
     ss = m->core->default_sample_spec;
@@ -1963,10 +2094,24 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (!(u->client = pa_socket_client_new_string(m->core->mainloop, true, u->server_name, PA_NATIVE_DEFAULT_PORT))) {
-        pa_log("Failed to connect to server '%s'", u->server_name);
-        goto fail;
-    }
+    for (;;) {
+        server_list = pa_strlist_pop(server_list, &u->server_name);
+
+        if (!u->server_name) {
+            pa_log("Failed to connect to server '%s'", server);
+            goto fail;
+        }
+
+        pa_log_debug("Trying to connect to %s...", u->server_name);
+
+        if (!(u->client = pa_socket_client_new_string(m->core->mainloop, true, u->server_name, PA_NATIVE_DEFAULT_PORT))) {
+            pa_xfree(u->server_name);
+            u->server_name = NULL;
+            continue;
+        }
+
+        break;
+     }
 
     pa_socket_client_set_callback(u->client, on_connection, u);
 
@@ -1978,7 +2123,7 @@ int pa__init(pa_module*m) {
     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);
@@ -2022,7 +2167,7 @@ int pa__init(pa_module*m) {
     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);
@@ -2079,6 +2224,17 @@ int pa__init(pa_module*m) {
     pa_source_put(u->source);
 #endif
 
+    if (server)
+        pa_xfree(server);
+
+    if (server_list)
+        pa_strlist_free(server_list);
+
+#ifdef HAVE_X11
+    if (xcb)
+        xcb_disconnect(xcb);
+#endif
+
     pa_modargs_free(ma);
 
     return 0;
@@ -2086,6 +2242,17 @@ int pa__init(pa_module*m) {
 fail:
     pa__done(m);
 
+    if (server)
+        pa_xfree(server);
+
+    if (server_list)
+        pa_strlist_free(server_list);
+
+#ifdef HAVE_X11
+    if (xcb)
+        xcb_disconnect(xcb);
+#endif
+
     if (ma)
         pa_modargs_free(ma);
 
diff --git a/src/pulsecore/auth-cookie.c b/src/pulsecore/auth-cookie.c
index c5e5d7c..a3d9ca4 100644
--- a/src/pulsecore/auth-cookie.c
+++ b/src/pulsecore/auth-cookie.c
@@ -77,6 +77,39 @@ pa_auth_cookie* pa_auth_cookie_get(pa_core *core, const char *cn, bool create, s
     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);
diff --git a/src/pulsecore/auth-cookie.h b/src/pulsecore/auth-cookie.h
index 7c689a4..e4a3504 100644
--- a/src/pulsecore/auth-cookie.h
+++ b/src/pulsecore/auth-cookie.h
@@ -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, bool create, 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);
 



More information about the pulseaudio-commits mailing list