X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/bd8895a87731c72190ea2012f36583f796d4181a..e02f980793337f4bf0b16bca957a3d112a67b62a:/lib/mixer.c diff --git a/lib/mixer.c b/lib/mixer.c index f674d68..a24f7eb 100644 --- a/lib/mixer.c +++ b/lib/mixer.c @@ -2,97 +2,112 @@ * This file is part of DisOrder * Copyright (C) 2007 Richard Kettlewell * - * This program is free software; you can redistribute it and/or modify + * 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 + * the Free Software Foundation, either version 3 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. - * + * + * 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 + * along with this program. If not, see . + */ +/** @file lib/mixer.c + * @brief Mixer support */ -#include -#include "types.h" - -#include -#include -#include -#include -#include -#include -#include -#include +#include "common.h" #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; -} - -int mixer_valid_channel(int api, const char *c) { - const struct mixer *const m = find_mixer(api); - - return m ? m->validate_channel(c) : 1; + return &mixer_none; } -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); } /*