summaryrefslogtreecommitdiffstats
path: root/src/modules/alsa
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/alsa')
-rw-r--r--src/modules/alsa/alsa-sink.c38
-rw-r--r--src/modules/alsa/alsa-source.c38
-rw-r--r--src/modules/alsa/alsa-util.c80
-rw-r--r--src/modules/alsa/alsa-util.h1
4 files changed, 83 insertions, 74 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index c56614c8..1474cfee 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -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 */
frame_size = pa_frame_size(&ss);
- if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
- 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_alsa_find_mixer_and_elem(u->pcm_handle, &u->mixer_handle, &u->mixer_elem);
pa_sink_new_data_init(&data);
data.driver = driver;
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 2b42d3f9..192645d0 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -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 */
frame_size = pa_frame_size(&ss);
- if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
- 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_alsa_find_mixer_and_elem(u->pcm_handle, &u->mixer_handle, &u->mixer_elem);
pa_source_new_data_init(&data);
data.driver = driver;
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! */
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 8a209348..8b083392 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -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);
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 {
pa_channel_map map;