chiark / gitweb /
clients/playrtp.c, lib/configuration.[ch]: Static config for `playrtp'.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 4 May 2020 17:30:54 +0000 (18:30 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 5 May 2020 22:18:28 +0000 (23:18 +0100)
The `disorder-playrtp' program already reads the client configuration.
This change sets defaults for a number of parameters which could
previously only be changed from the command line, which is a problem
because `disorder-playrtp' is commonly invoked by Disobedience which
doesn't allow one to set a command-line.

These various tweaks are experimental, and may change, or even be
removed, in some later version.  The `rtp_request_address' and
`rtp_always_request' options, in particular, might be replaced by some
more complicated policy mechanism.

clients/playrtp.c
doc/disorder-playrtp.1.in
doc/disorder_config.5.in
lib/configuration.c
lib/configuration.h

index 539dc5995c480b62b5d4a3d8fda2fdaad2bd0ae4..3a4757bf755d6c5b24f5913139325d08a42251a3 100644 (file)
@@ -74,6 +74,7 @@
 #include "configuration.h"
 #include "addr.h"
 #include "syscalls.h"
+#include "printf.h"
 #include "rtp.h"
 #include "defs.h"
 #include "vector.h"
@@ -99,7 +100,7 @@ static FILE *logfp;
 /** @brief Output device */
 
 /** @brief Buffer low watermark in samples */
-unsigned minbuffer = 4 * (2 * 44100) / 10;  /* 0.4 seconds */
+unsigned minbuffer;
 
 /** @brief Maximum buffer size in samples
  *
@@ -686,7 +687,7 @@ int main(int argc, char **argv) {
   struct addrinfo *res;
   struct stringlist sl;
   char *sockname;
-  int rcvbuf, target_rcvbuf = 0;
+  int rcvbuf, target_rcvbuf = -1;
   socklen_t len;
   struct ip_mreq mreq;
   struct ipv6_mreq mreq6;
@@ -767,20 +768,45 @@ int main(int argc, char **argv) {
      * CoreAudio/AudioHardware.h). */
     disorder_fatal(0, "cannot play RTP through RTP");
   }
-  if(!maxbuffer)
-    maxbuffer = 2 * minbuffer;
+  /* Set buffering parameters if not overridden */
+  if(!minbuffer) {
+    minbuffer = config->rtp_minbuffer;
+    if(!minbuffer) minbuffer = (2*44100)*4/10;
+  }
+  if(!maxbuffer) {
+    maxbuffer = config->rtp_maxbuffer;
+    if(!maxbuffer) maxbuffer = 2 * minbuffer;
+  }
+  if(target_rcvbuf < 0) target_rcvbuf = config->rtp_rcvbuf;
   argc -= optind;
   argv += optind;
   switch(argc) {
   case 0:
-    /* Get configuration from server */
-    if(!(c = disorder_new(1))) exit(EXIT_FAILURE);
-    if(disorder_connect(c)) exit(EXIT_FAILURE);
-    if(disorder_rtp_address(c, &address, &port)) exit(EXIT_FAILURE);
-    sl.n = 2;
-    sl.s = xcalloc(2, sizeof *sl.s);
-    sl.s[0] = address;
-    sl.s[1] = port;
+    sl.s = xcalloc(3, sizeof *sl.s);
+    if(config->rtp_always_request) {
+      sl.s[0] = sl.s[1] = (/*unconst*/ char *)"-";
+      sl.n = 2;
+    } else {
+      /* Get configuration from server */
+      if(!(c = disorder_new(1))) exit(EXIT_FAILURE);
+      if(disorder_connect(c)) exit(EXIT_FAILURE);
+      if(disorder_rtp_address(c, &address, &port)) exit(EXIT_FAILURE);
+      sl.s[0] = address;
+      sl.s[1] = port;
+      sl.n = 2;
+    }
+    /* If we're requesting a new stream then apply the local network address
+     * overrides.
+     */
+    if(!strcmp(sl.s[0], "-")) {
+      if(config->rtp_request_address.port)
+        byte_xasprintf(&sl.s[1], "%d", config->rtp_request_address.port);
+      if(config->rtp_request_address.address) {
+        sl.s[2] = sl.s[1];
+        sl.s[1] = config->rtp_request_address.address;
+        sl.n = 3;
+      }
+    }
     break;
   case 1: case 2: case 3:
     /* Use command-line ADDRESS+PORT or just PORT */
@@ -817,7 +843,8 @@ int main(int argc, char **argv) {
     /* If no address was given, pick something sensible based on the known-
      * working connectivity to the server */
     if(!node) {
-      int family = disorder_client_af(c);
+      int family = config->rtp_request_address.af;
+      if(family == AF_UNSPEC) family = disorder_client_af(c);
       /* Get a list of interfaces */
       struct ifaddrs *ifa, *bestifa = NULL;
       if(getifaddrs(&ifa) < 0)
index 5f4fa3f0af6374b0177f1871aefaccbe44eb86cd..d453dcbf4e5c8bb99ea30d103a83a3865b1ac45a 100644 (file)
@@ -126,18 +126,27 @@ You should consult the source code for details of their effects.
 .B \-\-min \fIFRAMES\fR, \fB\-m \fIFRAMES\fR
 Specifies the buffer low watermark in frames.
 This also acts as the target buffer occupancy.
+The default is taken from the
+.B rtp_minbuffer
+configuration parameter.
 .TP
 .B \-\-max \fIFRAMES\fR, \fB\-x \fIFRAMES\fR
 Specifies the maximum buffer size in frames.
 If there are this many frames in the buffer then reading from the
 network socket will be suspended.
 The default is twice the \fB\-\-min\fR value.
+The default is taken from the
+.B rtp_maxbuffer
+configuration parameter.
 .TP
 .B \-\-rcvbuf \fIBYTES\fR, \fB\-R \fIBYTES\fR
 Specifies socket receive buffer size.
 The default is not to change the buffer size, i.e. you get whatever the
 local operating system chooses.
 The buffer size will not be reduced below the operating system's default.
+The default is taken from the
+.B rtp_rcvbuf
+configuration parameter.
 .TP
 .B \-\-monitor\fR, \fB\-M
 Periodically report how close to the buffer low watermark the buffer is.
index 8f0c8f30f89e5a8d28b4c91166804d17ff04638b..e57e06ac246e5e9a956b3f32e52f8ec1db95885c 100644 (file)
@@ -654,6 +654,56 @@ anything currently listed in the recently-played list.
 New values of this option may be picked up from the configuration file even
 without a reload.
 .TP
+.B rtp_always_request yes\fR|\fBno
+If
+.B yes
+then
+.BR disorder-playrtp (1)
+will always request a dedicated RTP stream,
+rather than contacting the server to discover
+a broadcast or multicast address.
+(This behaviour can be overridden by
+setting a suitable address on the command-line.)
+The default is
+.BR no .
+.IP
+This option is experimental,
+and may change or be removed in a future release.
+.TP
+.B rtp_maxbuffer \fIFRAMES\fR
+Set
+.BR disorder-playrtp (1)'s
+buffer size to the given number of
+.IR FRAMES .
+If this is zero, then
+.B disorder-playrtp
+will select a default buffer size.
+(This setting can be overridden by passing
+a suitable command-line option.)
+The default value is
+.BR 0 .
+.IP
+This option is experimental,
+and may change or be removed in a future release.
+.TP
+.B rtp_minbuffer \fIFRAMES\fR
+Set
+.BR disorder-playrtp (1)'s
+buffer low-water-mark to the given number of
+.IR FRAMES .
+If this is zero, then
+.B disorder-playrtp
+will select a default low-water-mark.
+(This setting can be overridden by passing
+a suitable command-line option.)
+.IP
+This option is experimental,
+and may change or be removed in a future release.
+The default value is
+.BR 0 .
+.IP
+This option is experimental, and may change or be removed in a future release.
+.TP
 .B rtp_mode \fIMODE\fR
 The network transmission mode for the \fBrtp\fR backend.
 Possible values are:
@@ -676,6 +726,46 @@ Choose one of the above based on the destination address.
 This is the default, for backwards compatibility reasons.
 .RE
 .TP
+.B rtp_rcvbuf \fISIZE\fR
+Set
+.BR disorder-playrtp (1)'s
+socket receive buffer to at least
+.IB SIZE .
+(This setting can be overridden by passing
+a suitable command-line option.)
+The default value is
+.BR 0 .
+.IP
+This option is experimental,
+and may change or be removed in a future release.
+.TP
+.B rtp_request_address \fR[\fIFAMILY\fR] \fR[\fIHOST\fR] \fISERVICE\fR
+If
+.BR disorder-playrtp (1)
+is to request a unicast RTP stream,
+then it should establish its receiving socket
+to listen on the given address.
+The
+.I FAMILY
+and
+.I HOST
+may be omitted, in which case
+.B disorder-playrtp
+uses heuristics to determine suitable values.
+The
+.I PORT
+may be omitted, in which case
+.B disorder-playrtp
+uses a kernel-allocated port.
+(This setting can be overridden by passing
+a suitable address on the command line.)
+The default is
+.RB ` "\- 0" ',
+which uses a heuristically-chosen address and a kernel-allocated port.
+.IP
+This option is experimental,
+and may change or be removed in a future release.
+.TP
 .B sample_format \fIBITS\fB/\fIRATE\fB/\fICHANNELS
 Describes the sample format expected by the \fBspeaker_command\fR (below).
 The components of the format specification are as follows:
index bad315965f1e90f754d73f3b1e1aa1235db94b34..d1f14e90b001ef28a1fb60d3ef2dae54c38acc74 100644 (file)
@@ -1010,6 +1010,32 @@ static int validate_destaddr(const struct config_state attribute((unused)) *cs,
   return 0;
 }
 
+/** @brief Validate an internet address
+ * @param cs Configuration state
+ * @param nvec Length of (proposed) new value
+ * @param vec Elements of new value
+ * @return 0 on success, non-0 on error
+ *
+ * By a destination address, it is meant that it must be either IPv4 or IPv6.
+ */
+static int validate_inetaddr(const struct config_state *cs,
+                            int nvec, char **vec) {
+  struct netaddress na[1];
+
+  if(netaddress_parse(na, nvec, vec)) {
+    disorder_error(0, "%s:%d: invalid network address", cs->path, cs->line);
+    return -1;
+  }
+  switch(na->af) {
+    case AF_INET: case AF_INET6: case AF_UNSPEC: break;
+    default:
+      disorder_error(0, "%s:%d: must be an intenet address",
+                    cs->path, cs->line);
+      return -1;
+  }
+  return 0;
+}
+
 /** @brief Item name and and offset */
 #define C(x) #x, offsetof(struct config, x)
 /** @brief Item name and and offset */
@@ -1065,8 +1091,13 @@ static const struct conf conf[] = {
   { C(reminder_interval), &type_integer,         validate_positive },
   { C(remote_userman),   &type_boolean,          validate_any },
   { C(replay_min),       &type_integer,          validate_non_negative },
+  { C(rtp_always_request), &type_boolean,       validate_any },
   { C(rtp_delay_threshold), &type_integer,       validate_positive },
+  { C(rtp_maxbuffer),   &type_integer,          validate_non_negative },
+  { C(rtp_minbuffer),   &type_integer,          validate_non_negative },
   { C(rtp_mode),         &type_string,           validate_any },
+  { C(rtp_rcvbuf),      &type_integer,          validate_non_negative },
+  { C(rtp_request_address), &type_netaddress,   validate_inetaddr },
   { C(rtp_verbose),      &type_boolean,          validate_any },
   { C(sample_format),    &type_sample_format,    validate_sample_format },
   { C(scratch),          &type_string_accum,     validate_isreg },
index 148d08f60adda079a105ab00a797d39f34ce2a6c..5c33047d125c4a5552bec3bf97bf305328155b7b 100644 (file)
@@ -234,6 +234,22 @@ struct config {
   /** @brief RTP delay threshold */
   long rtp_delay_threshold;
 
+  /** @brief Whether to ignore the server's suggested RTP arrangement and
+   * always request a unicast stream */
+  int rtp_always_request;
+
+  /** @brief RTP buffer low-water mark */
+  long rtp_minbuffer;
+
+  /** @brief RTP buffer maximum size */
+  long rtp_maxbuffer;
+
+  /* @brief RTP receive buffer size */
+  long rtp_rcvbuf;
+
+  /** @brief Fixed RTP listening address */
+  struct netaddress rtp_request_address;
+
   /** @brief Verbose RTP transmission logging */
   int rtp_verbose;