{ "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 }
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) */
/* 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"
#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"
);
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;
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;
}
}
};
union any_sockaddr mgroup;
const char *dumpfile = 0;
- const char *device = 0;
pthread_t ltid;
static const struct addrinfo prefs = {
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;
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");
}
}
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(<id, 0, listen_thread, 0)))
/* 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;