disobedience, playrtp: Have `playrtp' handle volume control.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 20 Jul 2018 02:06:56 +0000 (03:06 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 20 Jul 2018 11:30:27 +0000 (12:30 +0100)
If the server is playing the audio directly, then it handles the volume
control too, as before.

If the server's transmitting using RTP, DisObedience /used/ to try to
twiddle the volume itself.  Instead, arrange for it to request volume
adjustment of the running `disorder-playrtp' instance via its socket
interface.

This has two advantages.

  * Firstly, `disorder-playrtp' actually knows which audio API it's
    using and therefore which method for fiddling with the volume will
    work best.  Indeed, DisObedience doesn't even have any configuration
    for selecting audio APIs, so it's only ever right by coincidence.
    On the other hand, `disorder-playrtp' has all of the necessary
    machinery.

  * Secondly, PulseAudio in particular has independent volume controls
    per input.  DisObedience has no hope of guessing which of these is
    the right one for `disorder-playrtp' without help, and it's cleaner
    just to give the whole job to `disorder-playrtp'.

clients/playrtp.c
disobedience/control.c
disobedience/disobedience.c
disobedience/disobedience.h
disobedience/rtp.c
doc/disorder-playrtp.1.in

index 707bbf9..1313a5e 100644 (file)
@@ -243,6 +243,7 @@ static void *control_thread(void attribute((unused)) *arg) {
   char *line;
   socklen_t salen;
   FILE *fp;
+  int vl, vr;
 
   assert(control_socket);
   unlink(control_socket);
@@ -276,9 +277,21 @@ static void *control_thread(void attribute((unused)) *arg) {
       if(!strcmp(line, "stop")) {
         disorder_info("stopped via %s", control_socket);
         exit(0);                          /* terminate immediately */
-      }
-      if(!strcmp(line, "query"))
+      } else if(!strcmp(line, "query"))
         fprintf(fp, "running");
+      else if(!strcmp(line, "getvol")) {
+        if(backend->get_volume) backend->get_volume(&vl, &vr);
+        else vl = vr = 0;
+        fprintf(fp, "%d %d\n", vl, vr);
+      } else if(!strncmp(line, "setvol ", 7)) {
+        if(!backend->set_volume)
+          vl = vr = 0;
+        else if(sscanf(line + 7, "%d %d", &vl, &vr) == 2)
+          backend->set_volume(&vl, &vr);
+        else
+          backend->get_volume(&vl, &vr);
+        fprintf(fp, "%d %d\n", vl, vr);
+      }
       xfree(line);
     }
     if(fclose(fp) < 0)
@@ -954,6 +967,7 @@ int main(int argc, char **argv) {
                     16/*bits/channel*/, 1/*signed*/);
   uaudio_set("application", "disorder-playrtp");
   backend->start(playrtp_callback, NULL);
+  if(backend->open_mixer) backend->open_mixer();
   /* We receive and convert audio data in a background thread */
   if((err = pthread_create(&ltid, 0, listen_thread, 0)))
     disorder_fatal(err, "pthread_create listen_thread");
index 663c815..6b3c106 100644 (file)
@@ -364,8 +364,7 @@ GtkWidget *control_widget(void) {
 static int volume_supported(void) {
   /* TODO: if the server doesn't know how to set the volume [but isn't using
    * network play] then we should have volume_supported = FALSE */
-  return (!rtp_supported
-          || (rtp_supported && backend && backend->set_volume));
+  return 1;
 }
 
 /** @brief Update the volume control when it changes */
@@ -493,8 +492,7 @@ static void volume_adjusted(GtkAdjustment attribute((unused)) *a,
    * from the log. */
   if(rtp_supported) {
     int l = nearbyint(left(v, b) * 100), r = nearbyint(right(v, b) * 100);
-    if(backend && backend->set_volume)
-      backend->set_volume(&l, &r);
+    rtp_setvol(&l, &r);
   } else
     disorder_eclient_set_volume(client, volume_completed,
                                 nearbyint(left(v, b) * 100),
index 3b5461f..d3e4d35 100644 (file)
@@ -71,9 +71,6 @@ int volume_l;
 /** @brief Right channel volume */
 int volume_r;
 
-/** @brief Audio backend */
-const struct uaudio *backend;
-
 double goesupto = 10;                   /* volume upper bound */
 
 /** @brief True if a NOP is in flight */
@@ -379,10 +376,9 @@ static gboolean periodic_fast(gpointer attribute((unused)) data) {
   }
   last = now;
 #endif
-  if(rtp_supported && backend && backend->get_volume) {
+  if(rtp_supported) {
     int nl, nr;
-    backend->get_volume(&nl, &nr);
-    if(nl != volume_l || nr != volume_r) {
+    if (!rtp_getvol(&nl, &nr) && (nl != volume_l || nr != volume_r)) {
       volume_l = nl;
       volume_r = nr;
       event_raise("volume-changed", 0);
@@ -574,12 +570,6 @@ int main(int argc, char **argv) {
   D(("create main loop"));
   mainloop = g_main_loop_new(0, 0);
   if(config_read(0, NULL)) disorder_fatal(0, "cannot read configuration");
-  /* we'll need mixer support */
-  backend = uaudio_default(uaudio_apis, UAUDIO_API_CLIENT);
-  if(backend->configure)
-    backend->configure();
-  if(backend->open_mixer)
-    backend->open_mixer();
   /* create the clients */
   if(!(client = gtkclient())
      || !(logclient = gtkclient()))
index 8e1d7f7..ab74592 100644 (file)
@@ -110,7 +110,6 @@ extern int choosealpha;                 /* break up choose by letter */
 extern int rtp_supported;
 extern int rtp_is_running;
 extern GtkItemFactory *mainmenufactory;
-extern const struct uaudio *backend;
 
 extern const disorder_eclient_log_callbacks log_callbacks;
 
@@ -252,6 +251,8 @@ void load_rtp_config(void);
 void save_rtp_config(void);
 void change_rtp_api(const char *api);
 const char *rtp_api;
+int rtp_setvol(int *l, int *r);
+int rtp_getvol(int *l, int *r);
 
 /* Settings */
 
index d88c3ec..bb71022 100644 (file)
@@ -97,6 +97,27 @@ int rtp_running(void) {
   return 1;
 }
 
+int rtp_getvol(int *l, int *r) {
+  FILE *fp;
+  int rc = -1;
+
+  fp = rtp_connect(); if(!fp) goto end;
+  fprintf(fp, "getvol\n"); fflush(fp);
+  if(fscanf(fp, "%d %d\n", l, r) != 2) goto end;
+  rc = 0;
+end:
+  if(fp) fclose(fp);
+  return rc;
+}
+
+int rtp_setvol(int *l, int *r) {
+  FILE *fp = rtp_connect(); if(!fp) return -1;
+  fprintf(fp, "setvol %d %d\n", *l, *r); fflush(fp);
+  if(fscanf(fp, "%d %d\n", l, r) != 2) { /* do nothing */ }
+  fclose(fp);
+  return 0;
+}
+
 /** @brief Activate the RTP player if it is not running */
 void start_rtp(void) {
   pid_t pid;
index 228ae60..0df5389 100644 (file)
@@ -165,6 +165,18 @@ to terminate.
 .TP
 .B query
 Causes the string "running" to be sent back.
+.TP
+.B getvol
+Print the left and right volume levels,
+as two decimal integers between 0 and 100,
+separated by a space.
+.TP
+.BI "setvol " left " " right
+Set the left and right volume levels to the given decimal values,
+which should be between 0 and 100;
+echo back the new values as for
+.B getvol
+above.
 .PP
 Other commands are ignored.
 After the first command the connection is closed.