If we cannot open an ALSA device with SND_PCM_NO_AUTO_FORMAT retry without
authorLennart Poettering <lennart@poettering.net>
Tue, 23 Dec 2008 14:14:28 +0000 (15:14 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Dec 2008 14:14:28 +0000 (15:14 +0100)
This should fix compatibility with some sound cards which only support
24 bit packed samples.

src/modules/alsa-util.c

index 7ae538a..203bdcd 100644 (file)
@@ -556,6 +556,7 @@ snd_pcm_t *pa_alsa_open_by_device_id(
 
     for (i = 0;; i += direction) {
         pa_sample_spec try_ss;
+        pa_bool_t reformat;
 
         if (i < 0) {
             pa_assert(direction == -1);
@@ -580,8 +581,9 @@ snd_pcm_t *pa_alsa_open_by_device_id(
 
         d = pa_sprintf_malloc("%s:%s", device_table[i].name, dev_id);
 
+        reformat = FALSE;
         for (;;) {
-            pa_log_debug("Trying %s...", d);
+            pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
 
             /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
              * 1.0.17a would then ignore the SND_PCM_NO_xxx
@@ -593,7 +595,7 @@ snd_pcm_t *pa_alsa_open_by_device_id(
                                     /* SND_PCM_NONBLOCK| */
                                     SND_PCM_NO_AUTO_RESAMPLE|
                                     SND_PCM_NO_AUTO_CHANNELS|
-                                    SND_PCM_NO_AUTO_FORMAT)) < 0) {
+                                    (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
                 pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err));
                 break;
             }
@@ -604,6 +606,12 @@ snd_pcm_t *pa_alsa_open_by_device_id(
 
             if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) {
 
+                if (!reformat) {
+                    reformat = TRUE;
+                    snd_pcm_close(pcm_handle);
+                    continue;
+                }
+
                 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
                     char *t;
 
@@ -611,6 +619,8 @@ snd_pcm_t *pa_alsa_open_by_device_id(
                     pa_xfree(d);
                     d = t;
 
+                    reformat = FALSE;
+
                     snd_pcm_close(pcm_handle);
                     continue;
                 }
@@ -655,6 +665,7 @@ snd_pcm_t *pa_alsa_open_by_device_string(
     int err;
     char *d;
     snd_pcm_t *pcm_handle;
+    pa_bool_t reformat = FALSE;
 
     pa_assert(device);
     pa_assert(dev);
@@ -666,7 +677,7 @@ snd_pcm_t *pa_alsa_open_by_device_string(
     d = pa_xstrdup(device);
 
     for (;;) {
-        pa_log_debug("Trying %s...", d);
+        pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
 
         /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
          * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
@@ -678,7 +689,7 @@ snd_pcm_t *pa_alsa_open_by_device_string(
                                 /*SND_PCM_NONBLOCK|*/
                                 SND_PCM_NO_AUTO_RESAMPLE|
                                 SND_PCM_NO_AUTO_CHANNELS|
-                                SND_PCM_NO_AUTO_FORMAT)) < 0) {
+                                (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
             pa_log("Error opening PCM device %s: %s", d, snd_strerror(err));
             pa_xfree(d);
             return NULL;
@@ -686,6 +697,13 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 
         if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE)) < 0) {
 
+            if (!reformat) {
+                reformat = TRUE;
+
+                snd_pcm_close(pcm_handle);
+                continue;
+            }
+
             /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
 
             if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
@@ -695,6 +713,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
                 pa_xfree(d);
                 d = t;
 
+                reformat = FALSE;
+
                 snd_pcm_close(pcm_handle);
                 continue;
             }