diff options
Diffstat (limited to 'src/modules/alsa/alsa-util.c')
-rw-r--r-- | src/modules/alsa/alsa-util.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index 5236d02f..d7caa0f0 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -1057,6 +1057,86 @@ success: return elem; } + +int pa_alsa_find_mixer_and_elem( + snd_pcm_t *pcm, + snd_mixer_t **_m, + snd_mixer_elem_t **_e) { + + int err; + snd_mixer_t *m; + snd_mixer_elem_t *e; + pa_bool_t found = FALSE; + const char *dev; + + pa_assert(pcm); + pa_assert(_m); + pa_assert(_e); + + if ((err = snd_mixer_open(&m, 0)) < 0) { + pa_log("Error opening mixer: %s", snd_strerror(err)); + return -1; + } + + /* First, try by name */ + if ((dev = snd_pcm_name(pcm))) + if (pa_alsa_prepare_mixer(m, dev) >= 0) + found = TRUE; + + /* Then, try by card index */ + if (!found) { + snd_pcm_info_t* info; + snd_pcm_info_alloca(&info); + + if (snd_pcm_info(pcm, info) >= 0) { + char *md; + int card_idx; + + if ((card_idx = snd_pcm_info_get_card(info)) >= 0) { + + md = pa_sprintf_malloc("hw:%i", card_idx); + + if (!dev || !pa_streq(dev, md)) + if (pa_alsa_prepare_mixer(m, md) >= 0) + found = TRUE; + + pa_xfree(md); + } + } + } + + if (!found) { + snd_mixer_close(m); + return -1; + } + + switch (snd_pcm_stream(pcm)) { + + case SND_PCM_STREAM_PLAYBACK: + e = pa_alsa_find_elem(m, "Master", "PCM", TRUE); + break; + + case SND_PCM_STREAM_CAPTURE: + e = pa_alsa_find_elem(m, "Capture", "Mic", FALSE); + break; + + default: + pa_assert_not_reached(); + } + + if (!e) { + snd_mixer_close(m); + return -1; + } + + pa_assert(e && m); + + *_m = m; + *_e = e; + + return 0; +} + static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_MAX] = { [PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */ |