From bd8895a87731c72190ea2012f36583f796d4181a Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Sun, 30 Dec 2007 16:20:37 +0000 Subject: [PATCH] Unify sound API configuration. Organization: Straylight/Edgeware From: rjk@greenend.org.uk <> 'speaker_backend' is now spelled 'api' (though the old name still works) and effects the choice of volume setting API as well as the device used by the speaker process. For volume setting, only OSS is implemented (still). The new structure means that ALSA volume setting no longer works as it will no longer use the OSS interface instead. However, this was never reliable as it depended upon ALSA's OSS emulation being enabled. --- README.streams | 2 +- doc/disorder_config.5.in | 103 ++++++++++++++---------- lib/Makefile.am | 2 +- lib/configuration.c | 66 ++++++++-------- lib/configuration.h | 4 +- lib/mixer-oss.c | 165 +++++++++++++++++++++++++++++++++++++++ lib/mixer.c | 110 +++++++++++--------------- lib/mixer.h | 49 +++++++++--- server/server.c | 2 +- server/speaker.c | 4 +- tests/dtest.py | 2 +- 11 files changed, 354 insertions(+), 155 deletions(-) create mode 100644 lib/mixer-oss.c diff --git a/README.streams b/README.streams index 9fe3e3a..8fbe6c7 100644 --- a/README.streams +++ b/README.streams @@ -13,7 +13,7 @@ To enable this make sure that all players use the speaker process, i.e. execraw rather than exec (or it won't work properly) and configure the network speaker backend: - speaker_backend network + api network broadcast 172.17.207.255 9003 broadcast_from 172.17.207.2 9002 diff --git a/doc/disorder_config.5.in b/doc/disorder_config.5.in index 78acb2a..a57a337 100644 --- a/doc/disorder_config.5.in +++ b/doc/disorder_config.5.in @@ -247,6 +247,34 @@ automatically included, but should include the proper extension. .IP The default is \fB{/artist}{/album}{/title}{ext}\fR. .TP +.B api \fINAME\fR +Selects the backend used to play sound and to set the volume. The following +options are available: +.RS +.TP +.B alsa +Use the ALSA API. This is only available on Linux systems, on which it is the +default. +.TP +.B coreaudio +Use Apple Core Audio. This only available on OS X systems, on which it is the +default. +.TP +.B oss +Use the OSS (/dev/dsp) API. Not available on all platforms. +.TP +.B command +Execute a command. This is the default if +.B speaker_command +is specified, or if no native is available. +.TP +.B network +Transmit audio over the network. This is the default if +\fBbroadcast\fR is specified. You can use +.BR disorder-playrtp (1) +to receive and play the resulting stream on Linux and OS X. +.RE +.TP .B authorization_algorithm \fIALGORITHM\fR Defines the algorithm used to authenticate clients. The valid options are sha1 (the default), sha256, sha384 and sha512. See @@ -255,7 +283,7 @@ for more details. .TP .B broadcast \fIADDRESS\fR \fIPORT\fR Transmit sound data to \fIADDRESS\fR using UDP port \fIPORT\fR. This implies -\fBspeaker_backend network\fR. +\fBapi network\fR. .IP See also \fBmulticast_loop\fR and \fBmulticast_ttl\fR. .TP @@ -263,9 +291,9 @@ See also \fBmulticast_loop\fR and \fBmulticast_ttl\fR. Sets the (local) source address used by \fBbroadcast\fR. .TP .B channel \fICHANNEL\fR -The mixer channel that the volume control should use. Valid names depend on -your operating system and hardware, but some standard ones that might be useful -are: +The mixer channel that the volume control should use. +.IP +For \fBapi oss\fR the possible values are: .RS .TP 8 .B pcm @@ -283,8 +311,11 @@ Master output level. The OSS documentation recommends against using this, as it affects all output devices. .RE .IP -You can also specify channels by number, if you know the right value. NB that -volume setting only works on OSS systems (including ALSA, via emulation). +You can also specify channels by number, if you know the right value. +.IP +For \fBapi alsa\fR, volume setting is not currently supported. +.IP +For \fBapi coreaudio\fR, volume setting is not currently supported. .TP .B collection \fIMODULE\fR \fIENCODING\fR \fIROOT\fR .TP @@ -321,8 +352,16 @@ The default is to allow everything except \fBadmin\fR and \fBregister\fR (modified in legacy configurations by the obsolete \fBrestrict\fR directive). .TP .B device \fINAME\fR -ALSA device to play raw-format audio. Default is \fBdefault\fR, i.e. to use -the whatever the ALSA configured default is. +Sound output device. +.IP +For \fBapi oss\fR this is the path to the device to use. If it is set to +\fBdefault\fR then \fI/dev/dsp\fR and \fI/dev/audio\fR will be tried. +.IP +For \fBapi alsa\fR this is the device name to use. +.IP +For \fBapi coreaudio\fR this is currently ignored. +.IP +The default is \fBdefault\fR. .TP .B gap \fISECONDS\fR Specifies the number of seconds to leave between tracks. The default @@ -344,19 +383,26 @@ Determines whether the server locks against concurrent operation. Default is \fByes\fR. There is no good reason to set this to \fBno\fR and the option will probably be removed in a future version. .TP -.B mixer \fIPATH\fR -The path to the mixer device, if you want access to the volume control, -e.g. \fB/dev/mixer\fR (the default). +.B mixer \fIDEVICE\fR +The mixer device name, if it needs to be specified separately from +\fBdevice\fR. +.IP +For \fBapi oss\fR this should be the path to the mixer device and the default +is \fI/dev/mixer\fR. +.IP +For \fBapi alsa\fR, volume setting is not currently supported. +.IP +For \fBapi coreaudio\fR, volume setting is not currently supported. .TP .B multicast_loop yes\fR|\fBno Determines whether multicast packets are loop backed to the sending host. The default is \fByes\fR. This only applies if -\fBspeaker_backend\fR is set to \fBnetwork\fR and \fBbroadcast\fR is actually a +\fBapi\fR is set to \fBnetwork\fR and \fBbroadcast\fR is actually a multicast address. .TP .B multicast_ttl \fIHOPS\fR Set the maximum number of hops to send multicast packets. This only applies if -\fBspeaker_backend\fR is set to \fBnetwork\fR and \fBbroadcast\fR is actually a +\fBapi\fR is set to \fBnetwork\fR and \fBbroadcast\fR is actually a multicast address. The default is 1. .TP .B namepart \fIPART\fR \fIREGEXP\fR \fISUBST\fR [\fICONTEXT\fR [\fIREFLAGS\fR]] @@ -518,40 +564,15 @@ scratched. The default is \fBSIGKILL\fR. Signals are specified by their full C name, i.e. \fBSIGINT\fR and not \fBINT\fR or \fBInterrupted\fR or whatever. .TP -.B speaker_backend \fINAME\fR -Selects the backend use by the speaker process. The following options are -available: -.RS -.TP -.B alsa -Use the ALSA API. This is only available on Linux systems, on which it is the -default. -.TP -.B coreaudio -Use Apple Core Audio. This only available on OS X systems, on which it is the -default. -.TP -.B oss -Use the OSS (/dev/dsp) API. Not available on all platforms. -.TP -.B command -Execute a command. This is the default if -.B speaker_command -is specified, or if no native is available. -.TP -.B network -Transmit audio over the network. This is the default if -\fBbroadcast\fR is specified. You can use -.BR disorder-playrtp (1) -to receive and play the resulting stream on Linux and OS X. -.RE -.TP .B sox_generation \fB0\fR|\fB1 Determines whether calls to \fBsox\fR(1) should use \fB-b\fR, \fB-x\fR, etc (if the generation is 0) or \fB-\fIbits\fR, \fB-L\fR etc (if it is 1). See the documentation for your installed copy of \fBsox\fR to determine which you need. The default is 0. .TP +.B speaker_backend \fINAME +This is an alias for \fBapi\fR; see above. +.TP .B speaker_command \fICOMMAND Causes the speaker subprocess to pipe audio data into shell command \fICOMMAND\fR, rather than writing to a local sound card. The sample format is diff --git a/lib/Makefile.am b/lib/Makefile.am index d658f86..3f526e6 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -48,7 +48,7 @@ libdisorder_a_SOURCES=charset.c charset.h \ logfd.c logfd.h \ mem.c mem.h mem-impl.h \ mime.h mime.c \ - mixer.c mixer.h \ + mixer.c mixer.h mixer-oss.c \ plugin.c plugin.h \ printf.c printf.h \ asprintf.c fprintf.c snprintf.c \ diff --git a/lib/configuration.c b/lib/configuration.c index 95720a3..db37837 100644 --- a/lib/configuration.c +++ b/lib/configuration.c @@ -679,12 +679,6 @@ static int validate_isreg(const struct config_state *cs, return 0; } -static int validate_ischr(const struct config_state *cs, - int nvec, char **vec) { - VALIDATE_FILE(S_ISCHR, "character device"); - return 0; -} - static int validate_player(const struct config_state *cs, int nvec, char attribute((unused)) **vec) { @@ -781,16 +775,6 @@ static int validate_sample_format(const struct config_state *cs, return parse_sample_format(cs, 0, nvec, vec); } -static int validate_channel(const struct config_state *cs, - int attribute((unused)) nvec, - char **vec) { - if(mixer_channel(vec[0]) == -1) { - error(0, "%s:%d: invalid channel '%s'", cs->path, cs->line, vec[0]); - return -1; - } - return 0; -} - static int validate_any(const struct config_state attribute((unused)) *cs, int attribute((unused)) nvec, char attribute((unused)) **vec) { @@ -937,10 +921,11 @@ static int validate_algo(const struct config_state attribute((unused)) *cs, static const struct conf conf[] = { { C(alias), &type_string, validate_alias }, { C(allow), &type_stringlist_accum, validate_allow }, + { C(api), &type_backend, validate_any }, { C(authorization_algorithm), &type_string, validate_algo }, { C(broadcast), &type_stringlist, validate_addrport }, { C(broadcast_from), &type_stringlist, validate_addrport }, - { C(channel), &type_string, validate_channel }, + { C(channel), &type_string, validate_any }, { C(checkpoint_kbyte), &type_integer, validate_non_negative }, { C(checkpoint_min), &type_integer, validate_non_negative }, { C(collection), &type_collections, validate_any }, @@ -956,7 +941,7 @@ static const struct conf conf[] = { { C(listen), &type_stringlist, validate_port }, { C(lock), &type_boolean, validate_any }, { C(mail_sender), &type_string, validate_any }, - { C(mixer), &type_string, validate_ischr }, + { C(mixer), &type_string, validate_any }, { C(multicast_loop), &type_boolean, validate_any }, { C(multicast_ttl), &type_integer, validate_non_negative }, { C(namepart), &type_namepart, validate_any }, @@ -978,7 +963,7 @@ static const struct conf conf[] = { { C(signal), &type_signal, validate_any }, { C(smtp_server), &type_string, validate_any }, { C(sox_generation), &type_integer, validate_non_negative }, - { C(speaker_backend), &type_backend, validate_any }, + { C2(speaker_backend, api), &type_backend, validate_any }, { C(speaker_command), &type_string, validate_any }, { C(stopword), &type_string_accum, validate_any }, { C(templates), &type_string_accum, validate_isdir }, @@ -1165,14 +1150,14 @@ static struct config *config_default(void) { c->sample_format.channels = 2; c->sample_format.endian = ENDIAN_NATIVE; c->queue_pad = 10; - c->speaker_backend = -1; + c->api = -1; c->multicast_ttl = 1; c->multicast_loop = 1; c->authorization_algorithm = xstrdup("sha1"); c->noticed_history = 31; c->short_display = 32; - c->mixer = xstrdup("/dev/mixer"); - c->channel = xstrdup("pcm"); + c->mixer = 0; + c->channel = 0; c->dbversion = 2; c->cookie_login_lifetime = 86400; c->cookie_key_lifetime = 86400 * 7; @@ -1247,31 +1232,31 @@ static void config_postdefaults(struct config *c, for(n = 0; n < NTRANSFORM; ++n) set_transform(&cs, whoami, 5, (char **)transform[n]); } - if(c->speaker_backend == -1) { + if(c->api == -1) { if(c->speaker_command) - c->speaker_backend = BACKEND_COMMAND; + c->api = BACKEND_COMMAND; else if(c->broadcast.n) - c->speaker_backend = BACKEND_NETWORK; + c->api = BACKEND_NETWORK; else { #if HAVE_ALSA_ASOUNDLIB_H - c->speaker_backend = BACKEND_ALSA; + c->api = BACKEND_ALSA; #elif HAVE_SYS_SOUNDCARD_H - c->speaker_backend = BACKEND_OSS; + c->api = BACKEND_OSS; #elif HAVE_COREAUDIO_AUDIOHARDWARE_H - c->speaker_backend = BACKEND_COREAUDIO; + c->api = BACKEND_COREAUDIO; #else - c->speaker_backend = BACKEND_COMMAND; + c->api = BACKEND_COMMAND; #endif } } if(server) { - if(c->speaker_backend == BACKEND_COMMAND && !c->speaker_command) - fatal(0, "speaker_backend is command but speaker_command is not set"); - if(c->speaker_backend == BACKEND_NETWORK && !c->broadcast.n) - fatal(0, "speaker_backend is network but broadcast is not set"); + if(c->api == BACKEND_COMMAND && !c->speaker_command) + fatal(0, "'api command' but speaker_command is not set"); + if(c->api == BACKEND_NETWORK && !c->broadcast.n) + fatal(0, "'api network' but broadcast is not set"); } /* Override sample format */ - switch(c->speaker_backend) { + switch(c->api) { case BACKEND_NETWORK: c->sample_format.rate = 44100; c->sample_format.channels = 2; @@ -1304,6 +1289,10 @@ static void config_postdefaults(struct config *c, r |= RIGHT_REMOVE_ANY; c->default_rights = rights_string(r); } + if(!c->mixer) + c->mixer = xstrdup(mixer_default_device(c->api)); + if(!c->channel) + c->channel = xstrdup(mixer_default_channel(c->api)); } /** @brief (Re-)read the config file @@ -1346,6 +1335,15 @@ int config_read(int server) { config_postdefaults(c, server); /* everything is good so we shall use the new config */ config_free(config); + /* final error checking */ + if(c->mixer && !mixer_valid_device(c->api, c->mixer)) { + error(0, "invalid mixer device: %s", c->mixer); + return -1; + } + if(c->channel && !mixer_valid_channel(c->api, c->channel)) { + error(0, "invalid mixer channel: %s", c->channel); + return -1; + } /* warn about obsolete directives */ if(c->restrictions) error(0, "'restrict' will be removed in a future version"); diff --git a/lib/configuration.h b/lib/configuration.h index d212a7a..f965bbd 100644 --- a/lib/configuration.h +++ b/lib/configuration.h @@ -177,12 +177,12 @@ struct config { /** @brief Sox syntax generation */ long sox_generation; - /** @brief Speaker backend + /** @brief API used to play sound * * Choices are @ref BACKEND_ALSA, @ref BACKEND_COMMAND or @ref * BACKEND_NETWORK. */ - int speaker_backend; + int api; #define BACKEND_ALSA 0 /**< Use ALSA (Linux only) */ #define BACKEND_COMMAND 1 /**< Execute a command */ #define BACKEND_NETWORK 2 /**< Transmit RTP */ diff --git a/lib/mixer-oss.c b/lib/mixer-oss.c new file mode 100644 index 0000000..7ab73a2 --- /dev/null +++ b/lib/mixer-oss.c @@ -0,0 +1,165 @@ +/* + * This file is part of DisOrder + * Copyright (C) 2004, 2007 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include "types.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "configuration.h" +#include "mixer.h" +#include "log.h" +#include "syscalls.h" + +#if HAVE_SYS_SOUNDCARD_H +#include + +/* documentation does not match implementation! */ +#ifndef SOUND_MIXER_READ +# define SOUND_MIXER_READ(x) MIXER_READ(x) +#endif +#ifndef SOUND_MIXER_WRITE +# define SOUND_MIXER_WRITE(x) MIXER_WRITE(x) +#endif + +static const char *channels[] = SOUND_DEVICE_NAMES; + +static int mixer_channel(const char *c) { + unsigned n; + + if(!c[strspn(c, "0123456789")]) + return atoi(c); + else { + for(n = 0; n < sizeof channels / sizeof *channels; ++n) + if(!strcmp(channels[n], c)) + return n; + return -1; + } +} + +static int oss_validate_channel(const char *c) { + if(mixer_channel(c) != -1) + return 1; + else + return 0; +} + +static int oss_validate_device(const char *d) { + struct stat sb; + + if(stat(d, &sb) < 0) { + error(errno, "%s", d); + return 0; + } + if(!S_ISCHR(sb.st_mode)) { + error(0, "%s: not a character device", d); + return 0; + } + return 1; +} + +static int oss_do_open(void) { + int fd; + + if((fd = open(config->mixer, O_RDWR, 0)) < 0) + error(errno, "error opening %s", config->mixer); + return fd; +} + +static int oss_do_get(int *left, int *right, int fd, int ch) { + int r; + + if(ioctl(fd, SOUND_MIXER_READ(ch), &r) == -1) { + error(errno, "error reading %s channel %s", + config->mixer, config->channel); + return -1; + } + *left = r & 0xff; + *right = (r >> 8) & 0xff; + return 0; +} + +static int oss_get(int *left, int *right) { + int ch, fd; + + if(config->mixer + && config->channel + && (ch = mixer_channel(config->channel)) != -1) { + if((fd = oss_do_open()) < 0) + return -1; + if(oss_do_get(left, right, fd, ch) < 0) { + xclose(fd); + return -1; + } + xclose(fd); + return 0; + } else + return -1; +} + +static int oss_set(int *left, int *right) { + int ch, fd, r; + + if(config->mixer + && config->channel + && (ch = mixer_channel(config->channel)) != -1) { + if((fd = oss_do_open()) < 0) + return -1; + r = (*left & 0xff) + (*right & 0xff) * 256; + if(ioctl(fd, SOUND_MIXER_WRITE(ch), &r) == -1) { + error(errno, "error changing %s channel %s", + config->mixer, config->channel); + xclose(fd); + return -1; + } + if(oss_do_get(left, right, fd, ch) < 0) { + xclose(fd); + return -1; + } + xclose(fd); + return 0; + } else + return -1; +} + +const struct mixer mixer_oss = { + BACKEND_OSS, + oss_validate_device, + oss_validate_channel, + oss_get, + oss_set, + "/dev/mixer", + "pcm" +}; +#endif + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +End: +*/ diff --git a/lib/mixer.c b/lib/mixer.c index 4fd4a9a..f674d68 100644 --- a/lib/mixer.c +++ b/lib/mixer.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder - * Copyright (C) 2004 Richard Kettlewell + * Copyright (C) 2007 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 @@ -35,81 +35,65 @@ #include "log.h" #include "syscalls.h" +static const struct mixer *mixers[] = { #if HAVE_SYS_SOUNDCARD_H -#include - -/* documentation does not match implementation! */ -#ifndef SOUND_MIXER_READ -# define SOUND_MIXER_READ(x) MIXER_READ(x) -#endif -#ifndef SOUND_MIXER_WRITE -# define SOUND_MIXER_WRITE(x) MIXER_WRITE(x) + &mixer_oss #endif +}; -static const char *channels[] = SOUND_DEVICE_NAMES; - -int mixer_channel(const char *c) { - unsigned n; - - if(!c[strspn(c, "0123456789")]) - return atoi(c); - else { - for(n = 0; n < sizeof channels / sizeof *channels; ++n) - if(!strcmp(channels[n], c)) - return n; - return -1; - } +#define NMIXERS (sizeof mixers / sizeof *mixers) + +static const struct mixer *find_mixer(int api) { + size_t n; + + for(n = 0; n < NMIXERS; ++n) + if(mixers[n]->api == api) + return mixers[n]; + return 0; +} + +int mixer_valid_channel(int api, const char *c) { + const struct mixer *const m = find_mixer(api); + + return m ? m->validate_channel(c) : 1; +} + +int mixer_valid_device(int api, const char *d) { + const struct mixer *const m = find_mixer(api); + + return m ? m->validate_device(d) : 1; } int mixer_control(int *left, int *right, int set) { - int fd, ch, r; - - if(config->mixer - && config->channel - && (ch = mixer_channel(config->channel)) != -1) { - if((fd = open(config->mixer, O_RDWR, 0)) < 0) { - error(errno, "error opening %s", config->mixer); - return -1; - } - if(set) { - r = (*left & 0xff) + (*right & 0xff) * 256; - if(ioctl(fd, SOUND_MIXER_WRITE(ch), &r) == -1) { - error(errno, "error changing %s channel %s", - config->mixer, config->channel); - xclose(fd); - return -1; - } - } - if(ioctl(fd, SOUND_MIXER_READ(ch), &r) == -1) { - error(errno, "error reading %s channel %s", - config->mixer, config->channel); - xclose(fd); - return -1; + const struct mixer *const m = find_mixer(config->api); + + if(m) { + if(set) + return m->set(left, right); + else + return m->get(left, right); + } else { + static int reported; + + if(!reported) { + error(0, "don't know how to get/set volume with this api"); + reported = 1; } - *left = r & 0xff; - *right = (r >> 8) & 0xff; - xclose(fd); - return 0; - } else return -1; + } } -#else -int mixer_channel(const char attribute((unused)) *c) { - return 0; + +const char *mixer_default_device(int api) { + const struct mixer *const m = find_mixer(api); + + return m ? m->device : ""; } -int mixer_control(int attribute((unused)) *left, - int attribute((unused)) *right, - int attribute((unused)) set) { - static int reported; +const char *mixer_default_channel(int api) { + const struct mixer *const m = find_mixer(api); - if(!reported) { - error(0, "don't know how to set volume on this platform"); - reported = 1; - } - return -1; + return m ? m->channel : ""; } -#endif /* Local Variables: diff --git a/lib/mixer.h b/lib/mixer.h index 07aab5d..cfbbce9 100644 --- a/lib/mixer.h +++ b/lib/mixer.h @@ -1,6 +1,6 @@ /* * This file is part of DisOrder - * Copyright (C) 2004 Richard Kettlewell + * Copyright (C) 2004, 2007 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 @@ -21,16 +21,47 @@ #ifndef MIXER_H #define MIXER_H -int mixer_channel(const char *c); -/* convert @c@ to a channel number, or return -1 if it does not match */ +/** @brief Definition of a mixer */ +struct mixer { + /** @brief API used by this mixer */ + int api; + /** @brief Return non-0 iff @p d is a valid device name */ + int (*validate_device)(const char *d); + + /** @brief Return non-0 iff @p c is a valid channel name */ + int (*validate_channel)(const char *c); + + /** @brief Get the volume + * @param left Where to store left-channel volume + * @param right Where to store right-channel volume + * @return 0 on success, non-0 on error + */ + int (*get)(int *left, int *right); + + /** @brief Set the volume + * @param left Pointer to target left-channel volume + * @param right Pointer to target right-channel volume + * @return 0 on success, non-0 on error + * + * @p left and @p right are updated with the actual volume set. + */ + int (*set)(int *left, int *right); + + /** @brief Default device */ + const char *device; + + /** @brief Default channel */ + const char *channel; +}; + +int mixer_valid_device(int api, const char *d); +int mixer_valid_channel(int api, const char *c); int mixer_control(int *left, int *right, int set); -/* get/set the current level. If @set@ is true then the level is set - * according to the pointers. In either case the eventual level is - * returned via the pointers. - * - * Returns 0 on success and -1 on error. - */ +const char *mixer_default_device(int api); +const char *mixer_default_channel(int api); + +extern const struct mixer mixer_oss; #endif /* MIXER_H */ diff --git a/server/server.c b/server/server.c index b680f2d..f0dfeb4 100644 --- a/server/server.c +++ b/server/server.c @@ -989,7 +989,7 @@ static int c_new(struct conn *c, static int c_rtp_address(struct conn *c, char attribute((unused)) **vec, int attribute((unused)) nvec) { - if(config->speaker_backend == BACKEND_NETWORK) { + if(config->api == BACKEND_NETWORK) { sink_printf(ev_writer_sink(c->w), "252 %s %s\n", quoteutf8(config->broadcast.s[0]), quoteutf8(config->broadcast.s[1])); diff --git a/server/speaker.c b/server/speaker.c index 8a3eb06..ae43f12 100644 --- a/server/speaker.c +++ b/server/speaker.c @@ -635,10 +635,10 @@ int main(int argc, char **argv) { if(getuid() == 0 || geteuid() == 0) fatal(0, "do not run as root"); /* identify the backend used to play */ for(n = 0; backends[n]; ++n) - if(backends[n]->backend == config->speaker_backend) + if(backends[n]->backend == config->api) break; if(!backends[n]) - fatal(0, "unsupported backend %d", config->speaker_backend); + fatal(0, "unsupported api %d", config->api); backend = backends[n]; /* backend-specific initialization */ backend->init(); diff --git a/tests/dtest.py b/tests/dtest.py index bca2b4a..982f4d4 100644 --- a/tests/dtest.py +++ b/tests/dtest.py @@ -191,7 +191,7 @@ tracklength *.mp3 disorder-tracklength tracklength *.ogg disorder-tracklength tracklength *.wav disorder-tracklength tracklength *.flac disorder-tracklength -speaker_backend network +api network broadcast 127.0.0.1 %d broadcast_from 127.0.0.1 %d mail_sender no.such.user.sorry@greenend.org.uk -- [mdw]