X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/e9b635a3223a51d0c30867e42ec4f9b54b62e591..e6c78eebe029d38415bccff0c66a44d9d2fad7f8:/clients/playrtp.c diff --git a/clients/playrtp.c b/clients/playrtp.c index 1263d7a..cbc24ae 100644 --- a/clients/playrtp.c +++ b/clients/playrtp.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder. - * Copyright (C) 2007 Richard Kettlewell + * Copyright (C) 2007, 2008 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 @@ -49,12 +49,9 @@ * - it is safe to read uint32_t values without a lock protecting them */ -#include -#include "types.h" +#include "common.h" #include -#include -#include #include #include #include @@ -62,8 +59,6 @@ #include #include #include -#include -#include #include #include #include @@ -85,6 +80,7 @@ #include "client.h" #include "playrtp.h" #include "inputline.h" +#include "version.h" #define readahead linux_headers_are_borked @@ -174,27 +170,42 @@ pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; /** @brief Condition variable signalled whenever @ref packets is changed */ pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -#if HAVE_ALSA_ASOUNDLIB_H -# define DEFAULT_BACKEND playrtp_alsa -#elif HAVE_SYS_SOUNDCARD_H || EMPEG_HOST -# define DEFAULT_BACKEND playrtp_oss -#elif HAVE_COREAUDIO_AUDIOHARDWARE_H -# define DEFAULT_BACKEND playrtp_coreaudio -#else -# error No known backend +#if DEFAULT_BACKEND == BACKEND_ALSA +# define DEFAULT_PLAYRTP_BACKEND playrtp_alsa +#elif DEFAULT_BACKEND == BACKEND_OSS +# define DEFAULT_PLAYRTP_BACKEND playrtp_oss +#elif DEFAULT_BACKEND == BACKEND_COREAUDIO +# define DEFAULT_PLAYRTP_BACKEND playrtp_coreaudio #endif /** @brief Backend to play with */ -static void (*backend)(void) = &DEFAULT_BACKEND; +static void (*backend)(void) = DEFAULT_PLAYRTP_BACKEND; HEAP_DEFINE(pheap, struct packet *, lt_packet); /** @brief Control socket or NULL */ const char *control_socket; +/** @brief Buffer for debugging dump + * + * The debug dump is enabled by the @c --dump option. It records the last 20s + * of audio to the specified file (which will be about 3.5Mbytes). The file is + * written as as ring buffer, so the start point will progress through it. + * + * Use clients/dump2wav to convert this to a WAV file, which can then be loaded + * into (e.g.) Audacity for further inspection. + * + * All three backends (ALSA, OSS, Core Audio) now support this option. + * + * The idea is to allow the user a few seconds to react to an audible artefact. + */ int16_t *dump_buffer; + +/** @brief Current index within debugging dump */ size_t dump_index; -size_t dump_size = 44100 * 2 * 20; /* 20s */ + +/** @brief Size of debugging dump in samples */ +size_t dump_size = 44100/*Hz*/ * 2/*channels*/ * 20/*seconds*/; static const struct option options[] = { { "help", no_argument, 0, 'h' }, @@ -312,8 +323,9 @@ static void *queue_thread(void attribute((unused)) *arg) { for(;;) { /* Get the next packet */ pthread_mutex_lock(&receive_lock); - while(!received_packets) + while(!received_packets) { pthread_cond_wait(&receive_cond, &receive_lock); + } p = received_packets; received_packets = p->next; if(!received_packets) @@ -411,8 +423,9 @@ static void *listen_thread(void attribute((unused)) *arg) { * out of order then we guarantee dropouts. But for now... */ if(nsamples >= maxbuffer) { pthread_mutex_lock(&lock); - while(nsamples >= maxbuffer) + while(nsamples >= maxbuffer) { pthread_cond_wait(&cond, &lock); + } pthread_mutex_unlock(&lock); } /* Add the packet to the receive queue */ @@ -435,8 +448,9 @@ void playrtp_fill_buffer(void) { while(nsamples) drop_first_packet(); info("Buffering..."); - while(nsamples < readahead) + while(nsamples < readahead) { pthread_cond_wait(&cond, &lock); + } next_timestamp = pheap_first(&packets)->timestamp; active = 1; } @@ -514,13 +528,6 @@ static void help(void) { exit(0); } -/* display version number and terminate */ -static void version(void) { - xprintf("disorder-playrtp version %s\n", disorder_version_string); - xfclose(stdout); - exit(0); -} - int main(int argc, char **argv) { int n, err; struct addrinfo *res; @@ -542,14 +549,10 @@ int main(int argc, char **argv) { const char *dumpfile = 0; static const struct addrinfo prefs = { - AI_PASSIVE, - PF_INET, - SOCK_DGRAM, - IPPROTO_UDP, - 0, - 0, - 0, - 0 + .ai_flags = AI_PASSIVE, + .ai_family = PF_INET, + .ai_socktype = SOCK_DGRAM, + .ai_protocol = IPPROTO_UDP }; mem_init(); @@ -557,7 +560,7 @@ int main(int argc, char **argv) { while((n = getopt_long(argc, argv, "hVdD:m:b:x:L:R:M:aocC:r", options, 0)) >= 0) { switch(n) { case 'h': help(); - case 'V': version(); + case 'V': version("disorder-playrtp"); case 'd': debugging = 1; break; case 'D': device = optarg; break; case 'm': minbuffer = 2 * atol(optarg); break;