From 063854700ea54b4fd277e945ee256c33d103f72d Mon Sep 17 00:00:00 2001 Message-Id: <063854700ea54b4fd277e945ee256c33d103f72d.1715290189.git.mdw@distorted.org.uk> From: Mark Wooding Date: Thu, 7 Nov 2013 16:53:00 +0000 Subject: [PATCH] uaudio: more sophisticated choice of default playback API Organization: Straylight/Edgeware From: Richard Kettlewell --- clients/playrtp.c | 9 +++++++-- disobedience/disobedience.c | 2 +- lib/configuration.c | 3 ++- lib/uaudio-alsa.c | 5 +++-- lib/uaudio-command.c | 3 ++- lib/uaudio-coreaudio.c | 1 + lib/uaudio-oss.c | 1 + lib/uaudio-rtp.c | 1 + lib/uaudio.c | 19 +++++++++++++++++-- lib/uaudio.h | 12 +++++++++++- 10 files changed, 46 insertions(+), 10 deletions(-) diff --git a/clients/playrtp.c b/clients/playrtp.c index c9005f8..61cf6ab 100644 --- a/clients/playrtp.c +++ b/clients/playrtp.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder. - * Copyright (C) 2007-2009 Richard Kettlewell + * Copyright (C) 2007-2009, 2011, 2013 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 @@ -648,7 +648,6 @@ int main(int argc, char **argv) { logdate = 1; mem_init(); if(!setlocale(LC_CTYPE, "")) disorder_fatal(errno, "error calling setlocale"); - backend = uaudio_apis[0]; while((n = getopt_long(argc, argv, "hVdD:m:x:L:R:aocC:re:P:M", options, 0)) >= 0) { switch(n) { case 'h': help(); @@ -678,6 +677,12 @@ int main(int argc, char **argv) { } } if(config_read(0, NULL)) disorder_fatal(0, "cannot read configuration"); + if(!backend) { + backend = uaudio_default(uaudio_apis, UAUDIO_API_CLIENT); + if(!backend) + disorder_fatal(0, "no default uaudio API found"); + disorder_info("default audio API %s", backend->name); + } if(backend == &uaudio_rtp) { /* This means that you have NO local sound output. This can happen if you * use a non-Apple GCC on a Mac (because it doesn't know how to compile diff --git a/disobedience/disobedience.c b/disobedience/disobedience.c index 0b6e099..564335c 100644 --- a/disobedience/disobedience.c +++ b/disobedience/disobedience.c @@ -538,7 +538,7 @@ int main(int argc, char **argv) { 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_apis[0]; + backend = uaudio_default(uaudio_apis, UAUDIO_API_CLIENT); if(backend->configure) backend->configure(); if(backend->open_mixer) diff --git a/lib/configuration.c b/lib/configuration.c index 351b151..e7698ec 100644 --- a/lib/configuration.c +++ b/lib/configuration.c @@ -1429,7 +1429,8 @@ static void config_postdefaults(struct config *c, else if(c->broadcast.af != -1) c->api = xstrdup("rtp"); else if(config_uaudio_apis) - c->api = xstrdup(config_uaudio_apis[0]->name); + c->api = xstrdup(uaudio_default(config_uaudio_apis, + UAUDIO_API_SERVER)->name); else c->api = xstrdup(""); } diff --git a/lib/uaudio-alsa.c b/lib/uaudio-alsa.c index 93c8e41..3ae056e 100644 --- a/lib/uaudio-alsa.c +++ b/lib/uaudio-alsa.c @@ -145,7 +145,7 @@ static void alsa_open(void) { } static void alsa_start(uaudio_callback *callback, - void *userdata) { + void *userdata) { if(uaudio_channels != 1 && uaudio_channels != 2) disorder_fatal(0, "asked for %d channels but only support 1 or 2", uaudio_channels); @@ -288,7 +288,8 @@ const struct uaudio uaudio_alsa = { .close_mixer = alsa_close_mixer, .get_volume = alsa_get_volume, .set_volume = alsa_set_volume, - .configure = alsa_configure + .configure = alsa_configure, + .flags = UAUDIO_API_CLIENT | UAUDIO_API_SERVER, }; #endif diff --git a/lib/uaudio-command.c b/lib/uaudio-command.c index 1c29c16..f93454a 100644 --- a/lib/uaudio-command.c +++ b/lib/uaudio-command.c @@ -125,7 +125,7 @@ static size_t command_play(void *buffer, size_t nsamples, unsigned flags) { } static void command_start(uaudio_callback *callback, - void *userdata) { + void *userdata) { const char *pausemode = uaudio_get("pause-mode", "silence"); unsigned flags = 0; @@ -163,6 +163,7 @@ const struct uaudio uaudio_command = { .activate = uaudio_thread_activate, .deactivate = uaudio_thread_deactivate, .configure = command_configure, + .flags = UAUDIO_API_CLIENT | UAUDIO_API_SERVER, }; /* diff --git a/lib/uaudio-coreaudio.c b/lib/uaudio-coreaudio.c index 73cc287..a240df3 100644 --- a/lib/uaudio-coreaudio.c +++ b/lib/uaudio-coreaudio.c @@ -195,6 +195,7 @@ const struct uaudio uaudio_coreaudio = { .activate = coreaudio_activate, .deactivate = coreaudio_deactivate, .configure = coreaudio_configure, + .flags = UAUDIO_API_CLIENT | UAUDIO_API_SERVER, }; #endif diff --git a/lib/uaudio-oss.c b/lib/uaudio-oss.c index abf0354..c3c3ac5 100644 --- a/lib/uaudio-oss.c +++ b/lib/uaudio-oss.c @@ -232,6 +232,7 @@ const struct uaudio uaudio_oss = { .get_volume = oss_get_volume, .set_volume = oss_set_volume, .configure = oss_configure, + .flags = UAUDIO_API_CLIENT | UAUDIO_API_SERVER, }; #endif diff --git a/lib/uaudio-rtp.c b/lib/uaudio-rtp.c index 3ce1cbe..173d5f3 100644 --- a/lib/uaudio-rtp.c +++ b/lib/uaudio-rtp.c @@ -382,6 +382,7 @@ const struct uaudio uaudio_rtp = { .activate = uaudio_thread_activate, .deactivate = uaudio_thread_deactivate, .configure = rtp_configure, + .flags = UAUDIO_API_SERVER, }; /* diff --git a/lib/uaudio.c b/lib/uaudio.c index 343290d..a9ac103 100644 --- a/lib/uaudio.c +++ b/lib/uaudio.c @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -75,7 +75,7 @@ char *uaudio_get(const char *name, const char *default_value) { return xstrdup(*valuep); } -/** @brief Set sample format +/** @brief Set sample format * @param rate Sample rate in KHz * @param channels Number of channels (i.e. 2 for stereo) * @param bits Number of bits per channel (typically 8 or 16) @@ -100,6 +100,21 @@ void uaudio_set_format(int rate, int channels, int bits, int signed_) { uaudio_sample_size = bits / CHAR_BIT; } +/** @brief Choose the default audio API by context + * @param apis Table of APIs or a null pointer + * @param context @ref UAUDIO_API_SERVER or @ref UAUDIO_API_CLIENT + * @return Default API or a null pointer + */ +const struct uaudio *uaudio_default(const struct uaudio *const *apis, + unsigned context) { + if(apis) { + for(int n = 0; apis[n]; ++n) + if(apis[n]->flags & context) + return apis[n]; + } + return 0; +} + /* Local Variables: c-basic-offset:2 diff --git a/lib/uaudio.h b/lib/uaudio.h index 709979e..2a32d40 100644 --- a/lib/uaudio.h +++ b/lib/uaudio.h @@ -149,9 +149,17 @@ struct uaudio { /** @brief Set configuration */ void (*configure)(void); - + + /** @brief Descriptive flags */ + unsigned flags; }; +/** @brief API is suitable for clients */ +#define UAUDIO_API_CLIENT 0x0001 + +/** @brief API is suitable for servers */ +#define UAUDIO_API_SERVER 0x0002 + void uaudio_set_format(int rate, int channels, int samplesize, int signed_); void uaudio_set(const char *name, const char *value); char *uaudio_get(const char *name, const char *default_value); @@ -169,6 +177,8 @@ uint32_t uaudio_schedule_sync(void); void uaudio_schedule_sent(size_t nsamples_sent); void uaudio_schedule_init(void); const struct uaudio *uaudio_find(const char *name); +const struct uaudio *uaudio_default(const struct uaudio *const *apis, + unsigned context); extern uint64_t uaudio_schedule_timestamp; extern int uaudio_schedule_reactivated; -- [mdw]