chiark / gitweb /
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 707bbf99994fa528cd9ac35d1d72b9a67e1d2e11..1313a5e6fe8a0396fc98b1847d75b555b83378d4 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 663c8155c916c39541e94ca5ae649d03e92bf47e..6b3c106a0f23e3acb5e1e3761154ff4738d6157f 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 3b5461f7af06a3dddda5640982ef93e4907c5531..d3e4d3523dc9dabc59788f3e8696990a31c8dc91 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 8e1d7f71836385bc4cff39742f005134a7448afd..ab74592932efba1170d9835ab48cc7b130b2090f 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 d88c3ec062f76f5e8ad095dbe293c80684219b78..bb71022a86f9566bb45f44b4da97642f13262fbc 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 228ae60bfdc613fd36405e31758d1dcfb22aa1fd..0df5389817a123984adab116b9386b1115d240ef 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.