chiark / gitweb /
Merge latest work from uniform audio branch. The only functional change
[disorder] / clients / playrtp.c
index f1eaebcc61a95823b14ba04dc2e3d559c8589a44..03e4ad2e297de1a3c10601f3c8c3c6418953a234 100644 (file)
@@ -216,6 +216,7 @@ static const struct option options[] = {
   { "core-audio", no_argument, 0, 'c' },
 #endif
   { "dump", required_argument, 0, 'r' },
+  { "command", required_argument, 0, 'e' },
   { "socket", required_argument, 0, 's' },
   { "config", required_argument, 0, 'C' },
   { 0, 0, 0, 0 }
@@ -399,7 +400,7 @@ static void *listen_thread(void attribute((unused)) *arg) {
     if(header.mpt & 0x80)
       p->flags |= IDLE;
     switch(header.mpt & 0x7F) {
-    case 10:
+    case 10:                            /* L16 */
       p->nsamples = (n - sizeof header) / sizeof(uint16_t);
       break;
       /* TODO support other RFC3551 media types (when the speaker does) */
@@ -474,7 +475,7 @@ struct packet *playrtp_next_packet(void) {
 /* display usage message and terminate */
 static void help(void) {
   xprintf("Usage:\n"
-         "  disorder-playrtp [OPTIONS] ADDRESS [PORT]\n"
+         "  disorder-playrtp [OPTIONS] [[ADDRESS] PORT]\n"
          "Options:\n"
           "  --device, -D DEVICE     Output device\n"
           "  --min, -m FRAMES        Buffer low water mark\n"
@@ -491,6 +492,7 @@ static void help(void) {
 #if HAVE_COREAUDIO_AUDIOHARDWARE_H
           "  --core-audio, -c        Use Core Audio to play audio\n"
 #endif
+          "  --command, -e COMMAND   Pipe audio to command\n"
          "  --help, -h              Display usage message\n"
          "  --version, -V           Display version number\n"
           );
@@ -498,7 +500,7 @@ static void help(void) {
   exit(0);
 }
 
-static size_t playrtp_callback(int16_t *buffer,
+static size_t playrtp_callback(void *buffer,
                                size_t max_samples,
                                void attribute((unused)) *userdata) {
   size_t samples;
@@ -543,12 +545,12 @@ static size_t playrtp_callback(int16_t *buffer,
     if(samples > max_samples)
       samples = max_samples;
     //info("infill by %zu", samples);
-    memset(buffer, 0, samples * sizeof *buffer);
+    memset(buffer, 0, samples * uaudio_sample_size);
   }
   /* Debug dump */
   if(dump_buffer) {
     for(size_t i = 0; i < samples; ++i) {
-      dump_buffer[dump_index++] = buffer[i];
+      dump_buffer[dump_index++] = ((int16_t *)buffer)[i];
       dump_index %= dump_size;
     }
   }
@@ -577,7 +579,6 @@ int main(int argc, char **argv) {
   };
   union any_sockaddr mgroup;
   const char *dumpfile = 0;
-  const char *device = 0;
   pthread_t ltid;
 
   static const struct addrinfo prefs = {
@@ -590,12 +591,12 @@ int main(int argc, char **argv) {
   mem_init();
   if(!setlocale(LC_CTYPE, "")) fatal(errno, "error calling setlocale");
   backend = uaudio_apis[0];
-  while((n = getopt_long(argc, argv, "hVdD:m:b:x:L:R:M:aocC:r", options, 0)) >= 0) {
+  while((n = getopt_long(argc, argv, "hVdD:m:b:x:L:R:M:aocC:re:", options, 0)) >= 0) {
     switch(n) {
     case 'h': help();
     case 'V': version("disorder-playrtp");
     case 'd': debugging = 1; break;
-    case 'D': device = optarg; break;
+    case 'D': uaudio_set("device", optarg); break;
     case 'm': minbuffer = 2 * atol(optarg); break;
     case 'b': readahead = 2 * atol(optarg); break;
     case 'x': maxbuffer = 2 * atol(optarg); break;
@@ -613,6 +614,7 @@ int main(int argc, char **argv) {
     case 'C': configfile = optarg; break;
     case 's': control_socket = optarg; break;
     case 'r': dumpfile = optarg; break;
+    case 'e': backend = &uaudio_command; uaudio_set("command", optarg); break;
     default: fatal(0, "invalid option");
     }
   }
@@ -742,10 +744,10 @@ int main(int argc, char **argv) {
       fatal(errno, "mapping %s", dumpfile);
     info("dumping to %s", dumpfile);
   }
-  /* Choose output device */
-  if(device)
-    uaudio_set("device", device);
-  /* Set up output */
+  /* Set up output.  Currently we only support L16 so there's no harm setting
+   * the format before we know what it is! */
+  uaudio_set_format(44100/*Hz*/, 2/*channels*/,
+                    16/*bits/channel*/, 1/*signed*/);
   backend->start(playrtp_callback, NULL);
   /* We receive and convert audio data in a background thread */
   if((err = pthread_create(&ltid, 0, listen_thread, 0)))
@@ -765,8 +767,9 @@ int main(int argc, char **argv) {
     /* Wait until the buffer empties out */
     while(nsamples >= minbuffer
          || (nsamples > 0
-             && contains(pheap_first(&packets), next_timestamp)))
+             && contains(pheap_first(&packets), next_timestamp))) {
       pthread_cond_wait(&cond, &lock);
+    }
     /* Stop playing for a bit until the buffer re-fills */
     backend->deactivate();
     active = 0;