chiark / gitweb /
disobedience, playrtp: Have `playrtp' handle volume control.
[disorder] / disobedience / rtp.c
index f5f91f039a77d3b5ba7c6f0ab1f108a0ae4ee775..bb71022a86f9566bb45f44b4da97642f13262fbc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of Disobedience
- * Copyright (C) 2007 Richard Kettlewell
+ * Copyright (C) 2007-2010 Richard Kettlewell
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -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;
@@ -107,30 +128,33 @@ void start_rtp(void) {
   /* double-fork so we don't have to wait() later */
   if(!(pid = xfork())) {
     if(setsid() < 0)
-      fatal(errno, "error calling setsid");
-    if(!(pid = xfork())) {
+      disorder_fatal(errno, "error calling setsid");
+    if(!xfork()) {
       /* grandchild */
       exitfn = _exit;
       /* log errors and output somewhere reasonably sane.  rtp_running()
        * will have made sure the directory exists. */
       if((fd = open(rtp_log, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0)
-       fatal(errno, "creating %s", rtp_log);
+       disorder_fatal(errno, "creating %s", rtp_log);
       if(dup2(fd, 1) < 0
         || dup2(fd, 2) < 0)
-       fatal(errno, "dup2");
+       disorder_fatal(errno, "dup2");
       if(close(fd) < 0)
-       fatal(errno, "close");
+       disorder_fatal(errno, "close");
       /* We don't want to hang onto whatever stdin was */
       if((fd = open("/dev/null", O_RDONLY)) < 0)
-        fatal(errno, "opening /dev/null");
+        disorder_fatal(errno, "opening /dev/null");
       if(dup2(fd, 0) < 0)
-        fatal(errno, "dup2");
+        disorder_fatal(errno, "dup2");
       if(close(fd) < 0)
-       fatal(errno, "close");
+       disorder_fatal(errno, "close");
       /* execute the player */
       execlp("disorder-playrtp",
-            "disorder-playrtp", "--socket", rtp_socket, (char *)0);
-      fatal(errno, "disorder-playrtp");
+            "disorder-playrtp",
+             "--socket", rtp_socket,
+             "--api", rtp_api,
+             (char *)0);
+      disorder_fatal(errno, "disorder-playrtp");
     } else {
       /* child */
       _exit(0);
@@ -152,6 +176,75 @@ void stop_rtp(void) {
   fclose(fp);
 }
 
+static char *rtp_config_file(void) {
+  static char *rtp_config;
+  const char *home = getenv("HOME");
+  if(!rtp_config)
+    byte_xasprintf(&rtp_config, "%s/.disorder/api", home);
+  return rtp_config;
+}
+
+const char *rtp_api;
+
+void load_rtp_config(void) {
+  char *rtp_config = rtp_config_file();
+  FILE *fp;
+  if((fp = fopen(rtp_config, "r"))) {
+    char *line;
+    if(inputline(rtp_config, fp, &line, '\n') == 0) {
+      for(int n = 0; uaudio_apis[n]; ++n)
+        if(!strcmp(uaudio_apis[n]->name, line))
+          rtp_api = line;
+    }
+    fclose(fp);
+  }
+  if(!rtp_api)
+    rtp_api = uaudio_default(uaudio_apis, UAUDIO_API_CLIENT)->name;
+}
+
+void save_rtp_config(void) {
+  if(rtp_api) {
+    char *rtp_config = rtp_config_file();
+    char *tmp;
+    byte_xasprintf(&tmp, "%s.tmp", rtp_config);
+    FILE *fp;
+    if(!(fp = fopen(tmp, "w"))){
+      fpopup_msg(GTK_MESSAGE_ERROR, "error opening %s: %s",
+                 tmp, strerror(errno));
+      return;
+    }
+    if(fprintf(fp, "%s\n", rtp_api) < 0) {
+      fpopup_msg(GTK_MESSAGE_ERROR, "error writing to %s: %s",
+                 tmp, strerror(errno));
+      fclose(fp);
+      return;
+    }
+    if(fclose(fp) < 0) {
+      fpopup_msg(GTK_MESSAGE_ERROR, "error closing %s: %s",
+                 tmp, strerror(errno));
+      return;
+    }
+    if(rename(tmp, rtp_config) < 0) {
+      fpopup_msg(GTK_MESSAGE_ERROR, "error renaming %s: %s",
+                 tmp, strerror(errno));
+    }
+  }
+}
+
+void change_rtp_api(const char *api) {
+  if(rtp_api && !strcmp(api, rtp_api))
+    return;                             /* no change */
+  int running = rtp_running();
+  if(running)
+    stop_rtp();
+  rtp_api = api;
+  save_rtp_config();
+  // TODO this is racy and does not work; the player doesn't shut down quickly
+  // enough.
+  if(running)
+    start_rtp();
+}
+
 /*
 Local Variables:
 c-basic-offset:2