[PATCH 29/30] pacat: Add --routing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 man/pacat.1.xml.in | 26 ++++++++++++++++++++++++++
 src/utils/pacat.c  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/man/pacat.1.xml.in b/man/pacat.1.xml.in
index 1c5a6c0..c546246 100644
--- a/man/pacat.1.xml.in
+++ b/man/pacat.1.xml.in
@@ -84,6 +84,32 @@ USA.
     </option>
 
     <option>
+      <p><opt>--routing</opt><arg>=NODES</arg></p>
+
+      <optdesc><p>Specify how the stream should be routed. The argument is
+      a comma-separated list of node names. The possibility to specify multiple
+      nodes exists so that the stream can be played to multiple devices
+      simultaneously. As of version 6.0, the server doesn't yet support this,
+      however.</p>
+
+      <p>The --device and --monitor-stream options also control the routing,
+      and to avoid confusion, it's not possible to use --routing together with
+      --device and --monitor-stream. Which option is "better", then? --routing
+      is the most recent addition, and it sort of supersedes both the --device
+      and --monitor-stream options, but sometimes it may be more convenient to
+      use the old options. Choose whichever option suits you best.</p>
+
+      <p>As of PulseAudio 6.0, there is one significant drawback with --routing
+      compared to --device: the node names for devices are not "stable", which
+      means that the node name of a device can be different after a reboot or
+      after the device has been removed and added back to the system. Sink and
+      source names, which are used with the --device option, tend to stay the
+      same for longer times (ideally forever, but we can't really promise
+      that). This problem with node names will hopefully go away eventually.
+      </p></optdesc>
+    </option>
+
+    <option>
       <p><opt>--monitor-stream</opt><arg>=INDEX</arg></p>
 
       <optdesc><p>Record from the sink input with index INDEX.</p></optdesc>
diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index e1abc31..ea68236 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -41,6 +41,7 @@
 #include <pulse/rtclock.h>
 
 #include <pulsecore/core-util.h>
+#include <pulsecore/dynarray.h>
 #include <pulsecore/i18n.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
@@ -67,6 +68,7 @@ static pa_io_event* stdio_event = NULL;
 
 static pa_proplist *proplist = NULL;
 static char *device = NULL;
+static pa_dynarray *routing = NULL;
 
 static SNDFILE* sndfile = NULL;
 
@@ -449,6 +451,8 @@ static void stream_event_callback(pa_stream *s, const char *name, pa_proplist *p
 
 /* This is called whenever the context status changes */
 static void context_state_callback(pa_context *c, void *userdata) {
+    int r;
+
     pa_assert(c);
 
     switch (pa_context_get_state(c)) {
@@ -482,6 +486,15 @@ static void context_state_callback(pa_context *c, void *userdata) {
             pa_stream_set_event_callback(stream, stream_event_callback, NULL);
             pa_stream_set_buffer_attr_callback(stream, stream_buffer_attr_callback, NULL);
 
+            if (pa_dynarray_size(routing) > 0) {
+                r = pa_stream_set_initial_routing(stream, (const char * const *) pa_dynarray_get_raw_array(routing),
+                                                  pa_dynarray_size(routing));
+                if (r < 0) {
+                    pa_log("pa_stream_set_initial_routing() failed: %s", pa_strerror(r));
+                    goto fail;
+                }
+            }
+
             pa_zero(buffer_attr);
             buffer_attr.maxlength = (uint32_t) -1;
             buffer_attr.prebuf = (uint32_t) -1;
@@ -677,6 +690,7 @@ static void help(const char *argv0) {
              "  -v, --verbose                         Enable verbose operations\n\n"
              "  -s, --server=SERVER                   The name of the server to connect to\n"
              "  -d, --device=DEVICE                   The name of the sink/source to connect to\n"
+             "      --routing=NODES                   Comma-separated list of node names\n"
              "  -n, --client-name=NAME                How to call this client on the server\n"
              "      --stream-name=NAME                How to call this stream on the server\n"
              "      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
@@ -710,6 +724,7 @@ static void help(const char *argv0) {
 
 enum {
     ARG_VERSION = 256,
+    ARG_ROUTING,
     ARG_STREAM_NAME,
     ARG_VOLUME,
     ARG_SAMPLERATE,
@@ -746,6 +761,7 @@ int main(int argc, char *argv[]) {
         {"record",       0, NULL, 'r'},
         {"playback",     0, NULL, 'p'},
         {"device",       1, NULL, 'd'},
+        {"routing",      1, NULL, ARG_ROUTING},
         {"server",       1, NULL, 's'},
         {"client-name",  1, NULL, 'n'},
         {"stream-name",  1, NULL, ARG_STREAM_NAME},
@@ -797,6 +813,7 @@ int main(int argc, char *argv[]) {
     }
 
     proplist = pa_proplist_new();
+    routing = pa_dynarray_new(pa_xfree);
 
     while ((c = getopt_long(argc, argv, "rpd:s:n:hv", long_options, NULL)) != -1) {
 
@@ -829,6 +846,21 @@ int main(int argc, char *argv[]) {
                 device = pa_xstrdup(optarg);
                 break;
 
+            case ARG_ROUTING: {
+                char *node_name;
+                const char *split_state = NULL;
+
+                if (!*optarg) {
+                    pa_log(_("Invalid value passed to --routing: empty string."));
+                    goto quit;
+                }
+
+                while ((node_name = pa_split(optarg, ",", &split_state)))
+                    pa_dynarray_append(routing, node_name);
+
+                break;
+            }
+
             case 's':
                 pa_xfree(server);
                 server = pa_xstrdup(optarg);
@@ -1003,6 +1035,16 @@ int main(int argc, char *argv[]) {
         goto quit;
     }
 
+    if (device && pa_dynarray_size(routing) > 0) {
+        pa_log(_("--device and --routing are mutually exclusive options."));
+        goto quit;
+    }
+
+    if (monitor_stream != PA_INVALID_INDEX && pa_dynarray_size(routing) > 0) {
+        pa_log(_("--monitor-stream and --routing are mutually exclusive options."));
+        goto quit;
+    }
+
     if (optind+1 == argc) {
         int fd;
 
@@ -1226,6 +1268,10 @@ quit:
     pa_xfree(buffer);
 
     pa_xfree(server);
+
+    if (routing)
+        pa_dynarray_free(routing);
+
     pa_xfree(device);
 
     if (sndfile)
-- 
1.8.3.1



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux