mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
unify ALSA mixer initialization
This commit is contained in:
parent
023998e3c8
commit
6790c03f91
4 changed files with 83 additions and 74 deletions
|
|
@ -1386,43 +1386,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||||
/* ALSA might tweak the sample spec, so recalculate the frame size */
|
/* ALSA might tweak the sample spec, so recalculate the frame size */
|
||||||
frame_size = pa_frame_size(&ss);
|
frame_size = pa_frame_size(&ss);
|
||||||
|
|
||||||
if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
|
pa_alsa_find_mixer_and_elem(u->pcm_handle, &u->mixer_handle, &u->mixer_elem);
|
||||||
pa_log_warn("Error opening mixer: %s", snd_strerror(err));
|
|
||||||
else {
|
|
||||||
pa_bool_t found = FALSE;
|
|
||||||
|
|
||||||
if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
|
|
||||||
found = TRUE;
|
|
||||||
else {
|
|
||||||
snd_pcm_info_t *info;
|
|
||||||
|
|
||||||
snd_pcm_info_alloca(&info);
|
|
||||||
|
|
||||||
if (snd_pcm_info(u->pcm_handle, 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 (strcmp(u->device_name, md))
|
|
||||||
if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
|
|
||||||
found = TRUE;
|
|
||||||
pa_xfree(md);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM", TRUE)))
|
|
||||||
found = FALSE;
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
snd_mixer_close(u->mixer_handle);
|
|
||||||
u->mixer_handle = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pa_sink_new_data_init(&data);
|
pa_sink_new_data_init(&data);
|
||||||
data.driver = driver;
|
data.driver = driver;
|
||||||
|
|
|
||||||
|
|
@ -1211,43 +1211,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
/* ALSA might tweak the sample spec, so recalculate the frame size */
|
/* ALSA might tweak the sample spec, so recalculate the frame size */
|
||||||
frame_size = pa_frame_size(&ss);
|
frame_size = pa_frame_size(&ss);
|
||||||
|
|
||||||
if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
|
pa_alsa_find_mixer_and_elem(u->pcm_handle, &u->mixer_handle, &u->mixer_elem);
|
||||||
pa_log("Error opening mixer: %s", snd_strerror(err));
|
|
||||||
else {
|
|
||||||
pa_bool_t found = FALSE;
|
|
||||||
|
|
||||||
if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
|
|
||||||
found = TRUE;
|
|
||||||
else {
|
|
||||||
snd_pcm_info_t* info;
|
|
||||||
|
|
||||||
snd_pcm_info_alloca(&info);
|
|
||||||
|
|
||||||
if (snd_pcm_info(u->pcm_handle, 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 (strcmp(u->device_name, md))
|
|
||||||
if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
|
|
||||||
found = TRUE;
|
|
||||||
pa_xfree(md);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
|
||||||
if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic", FALSE)))
|
|
||||||
found = FALSE;
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
snd_mixer_close(u->mixer_handle);
|
|
||||||
u->mixer_handle = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pa_source_new_data_init(&data);
|
pa_source_new_data_init(&data);
|
||||||
data.driver = driver;
|
data.driver = driver;
|
||||||
|
|
|
||||||
|
|
@ -1057,6 +1057,86 @@ success:
|
||||||
return elem;
|
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] = {
|
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! */
|
[PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min);
|
||||||
|
|
||||||
int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev);
|
int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev);
|
||||||
snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback);
|
snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback);
|
||||||
|
int pa_alsa_find_mixer_and_elem(snd_pcm_t *pcm, snd_mixer_t **_m, snd_mixer_elem_t **_e);
|
||||||
|
|
||||||
typedef struct pa_alsa_profile_info {
|
typedef struct pa_alsa_profile_info {
|
||||||
pa_channel_map map;
|
pa_channel_map map;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue