X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/bd8895a87731c72190ea2012f36583f796d4181a..0e2b222fc14b8f890fab644118cf0f43abbe450a:/lib/mixer.c diff --git a/lib/mixer.c b/lib/mixer.c index f674d68..ee88fbb 100644 --- a/lib/mixer.c +++ b/lib/mixer.c @@ -17,82 +17,100 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ +/** @file lib/mixer.c + * @brief Mixer support + */ #include #include "types.h" -#include -#include -#include -#include -#include -#include -#include -#include - #include "configuration.h" #include "mixer.h" #include "log.h" -#include "syscalls.h" +#include "mem.h" + +/** @brief Whether lack of volume support has been reported yet */ +static int none_reported; + +/** @brief Get/set volume stub if volume control is not supported */ +static int none_get_set(int attribute((unused)) *left, + int attribute((unused)) *right) { + if(!none_reported) { + error(0, "don't know how to get/set volume with this api"); + none_reported = 1; + } + return -1; +} + +/** @brief Stub mixer control */ +static const struct mixer mixer_none = { + -1, + none_get_set, + none_get_set, + "", + "" +}; +/** @brief Table of mixer definitions */ static const struct mixer *mixers[] = { #if HAVE_SYS_SOUNDCARD_H - &mixer_oss + &mixer_oss, +#endif +#if HAVE_ALSA_ASOUNDLIB_H + &mixer_alsa, #endif + &mixer_none /* make sure array is never empty */ }; +/** @brief Number of mixer definitions */ #define NMIXERS (sizeof mixers / sizeof *mixers) +/** @brief Find the mixer definition */ static const struct mixer *find_mixer(int api) { size_t n; + if(api == -1) + api = config->api; for(n = 0; n < NMIXERS; ++n) if(mixers[n]->api == api) return mixers[n]; - return 0; + return &mixer_none; } -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) { - 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; - } - return -1; - } -} - -const char *mixer_default_device(int api) { +/** @brief Return true if we know how to drive the mixer + * @param api Sound api or -1 for default + * @return true if suppored, false otherwise + */ +int mixer_supported(int api) { const struct mixer *const m = find_mixer(api); - - return m ? m->device : ""; + return m != &mixer_none; } -const char *mixer_default_channel(int api) { +/** @brief Get/set volume + * @param api Sound api or -1 for default + * @param left Left channel level, 0-100 + * @param right Right channel level, 0-100 + * @param set Set volume if non-0 + * @return 0 on success, non-0 on error + * + * If getting the volume then @p left and @p right are filled in. + * + * If setting the volume then the target levels are read from @p left and + * @p right, and the actual level set is stored in them. + */ +int mixer_control(int api, int *left, int *right, int set) { const struct mixer *const m = find_mixer(api); - return m ? m->channel : ""; + /* We impose defaults bizarrely late, but this has the advantage of + * not making everything depend on sound libraries */ + if(!config->mixer) + config->mixer = xstrdup(m->device); + if(!config->channel) + config->channel = xstrdup(m->channel); + if(set) + return m->set(left, right); + else + return m->get(left, right); } /*