]> code.delx.au - pulseaudio/commitdiff
unify ALSA mixer initialization
authorLennart Poettering <lennart@poettering.net>
Fri, 13 Feb 2009 23:21:36 +0000 (00:21 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 13 Feb 2009 23:21:36 +0000 (00:21 +0100)
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c
src/modules/alsa/alsa-util.c
src/modules/alsa/alsa-util.h

index c56614c8ceaff614daf11e799499b9d625eac50f..1474cfee15c6b1bd440a38c7cdcf4d3ed2f232d3 100644 (file)
@@ -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;
index 2b42d3f927752ce43d440590eb5b17eaa118ecc3..192645d0e7f1efb2cb3a9210b700cafa7c79e733 100644 (file)
@@ -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;
index 5236d02fecb927d592e5e4b7ce01bfb33cf329d2..d7caa0f03b27098251ece0dc772242692da65e10 100644 (file)
@@ -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! */
 
index 8a209348bcadbee405ef980f7249a2dc4f3c53da..8b0833928b873ae2118d5b09a1ef04dfc260c26a 100644 (file)
@@ -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;