]> code.delx.au - pulseaudio/commitdiff
Add SPDIF/HDMI ALSA devices and device descriptions to device search table
authorLennart Poettering <lennart@poettering.net>
Thu, 15 Jan 2009 22:46:42 +0000 (23:46 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 15 Jan 2009 22:46:42 +0000 (23:46 +0100)
src/modules/alsa/alsa-util.c
src/modules/alsa/alsa-util.h
src/modules/alsa/module-alsa-sink.c
src/modules/alsa/module-alsa-source.c
src/pulse/proplist.h

index ff3af19d0b2818678de96d7f21e95e0b0de10578..871471f14c33dee5c88a60061f142e4eabffc3e3 100644 (file)
@@ -474,33 +474,81 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) {
 
 struct device_info {
     pa_channel_map map;
+    const char *alsa_name;
+    const char *description;
     const char *name;
 };
 
 static const struct device_info device_table[] = {
-    {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } }, "front" },
+    {{ 1, { PA_CHANNEL_POSITION_MONO }},
+     "hw",
+     "Analog Mono",
+     "analog-mono" },
+
+    {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
+     "front",
+     "Analog Stereo",
+     "analog-stereo" },
+
+    {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
+     "iec958",
+     "IEC958 Digital Stereo",
+     "iec958-stereo" },
+
+    {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
+     "hdmi",
+     "HDMI Digital Stereo",
+     "hdmi-stereo"},
 
     {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
-            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }}, "surround40" },
+            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
+     "surround40",
+     "Analog Surround 4.0",
+     "analog-surround-40" },
+
+    {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
+            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
+     "a52",
+     "IEC958/AC3 Digital Surround 4.0",
+     "iec958-ac3-surround-40" },
 
     {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
-            PA_CHANNEL_POSITION_LFE }}, "surround41" },
+            PA_CHANNEL_POSITION_LFE }},
+     "surround41",
+     "Analog Surround 4.1",
+     "analog-surround-41"},
 
     {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
-            PA_CHANNEL_POSITION_CENTER }}, "surround50" },
+            PA_CHANNEL_POSITION_CENTER }},
+     "surround50",
+     "Analog Surround 5.0",
+     "analog-surround-50" },
 
     {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
-            PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }}, "surround51" },
+            PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }},
+     "surround51",
+     "Analog Surround 5.1",
+     "analog-surround-51" },
+
+    {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_CENTER,
+            PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT,
+            PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE}},
+     "a52",
+     "IEC958/AC3 Digital Surround 5.1",
+     "iec958-ac3-surround-51" },
 
     {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
             PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE,
-            PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }} , "surround71" },
+            PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }},
+     "surround71",
+     "Analog Surround 7.1",
+     "analog-surround-71" },
 
-    {{ 0, { 0 }}, NULL }
+    {{ 0, { 0 }}, NULL, NULL, NULL }
 };
 
 static pa_bool_t channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
@@ -532,7 +580,9 @@ snd_pcm_t *pa_alsa_open_by_device_id(
         snd_pcm_uframes_t *period_size,
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
-        pa_bool_t *use_tsched) {
+        pa_bool_t *use_tsched,
+        const char**config_description,
+        const char **config_name) {
 
     int i;
     int direction = 1;
@@ -554,90 +604,122 @@ snd_pcm_t *pa_alsa_open_by_device_id(
      * way, we iterate backwards, and check all devices that do not
      * provide a superset of the requested channel map.*/
 
-    for (i = 0;; i += direction) {
+    i = 0;
+    for (;;) {
         pa_sample_spec try_ss;
         pa_bool_t reformat;
 
-        if (i < 0) {
-            pa_assert(direction == -1);
-
-            /* OK, so we iterated backwards, and now are at the
-             * beginning of our list. */
+        if ((direction > 0) == channel_map_superset(&device_table[i].map, map)) {
+            pa_log_debug("Checking for %s (%s)", device_table[i].name, device_table[i].alsa_name);
 
-            break;
+            d = pa_sprintf_malloc("%s:%s", device_table[i].alsa_name, dev_id);
 
-        } else if (!device_table[i].name) {
-            pa_assert(direction == 1);
+            reformat = FALSE;
+            for (;;) {
+                pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
 
-            /* OK, so we are at the end of our list. at iterated
-             * forwards. */
+                /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
+                 * 1.0.17a would then ignore the SND_PCM_NO_xxx
+                 * flags. Instead we enable nonblock mode afterwards via
+                 * snd_pcm_nonblock(). Also see
+                 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
 
-            i--;
-            direction = -1;
-        }
+                if ((err = snd_pcm_open(&pcm_handle, d, mode,
+                                        /* SND_PCM_NONBLOCK| */
+                                        SND_PCM_NO_AUTO_RESAMPLE|
+                                        SND_PCM_NO_AUTO_CHANNELS|
+                                        (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
+                    pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err));
+                    break;
+                }
 
-        if ((direction > 0) == !channel_map_superset(&device_table[i].map, map))
-            continue;
+                try_ss.channels = device_table[i].map.channels;
+                try_ss.rate = ss->rate;
+                try_ss.format = ss->format;
 
-        d = pa_sprintf_malloc("%s:%s", device_table[i].name, dev_id);
+                if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) {
 
-        reformat = FALSE;
-        for (;;) {
-            pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
+                    if (!reformat) {
+                        reformat = TRUE;
+                        snd_pcm_close(pcm_handle);
+                        continue;
+                    }
 
-            /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
-             * 1.0.17a would then ignore the SND_PCM_NO_xxx
-             * flags. Instead we enable nonblock mode afterwards via
-             * snd_pcm_nonblock(). Also see
-             * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
+                    if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
+                        char *t;
 
-            if ((err = snd_pcm_open(&pcm_handle, d, mode,
-                                    /* SND_PCM_NONBLOCK| */
-                                    SND_PCM_NO_AUTO_RESAMPLE|
-                                    SND_PCM_NO_AUTO_CHANNELS|
-                                    (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
-                pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err));
-                break;
-            }
+                        t = pa_sprintf_malloc("plug:%s", d);
+                        pa_xfree(d);
+                        d = t;
 
-            try_ss.channels = device_table[i].map.channels;
-            try_ss.rate = ss->rate;
-            try_ss.format = ss->format;
+                        reformat = FALSE;
 
-            if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) {
+                        snd_pcm_close(pcm_handle);
+                        continue;
+                    }
 
-                if (!reformat) {
-                    reformat = TRUE;
+                    pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err));
                     snd_pcm_close(pcm_handle);
-                    continue;
+                    break;
                 }
 
-                if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
-                    char *t;
-
-                    t = pa_sprintf_malloc("plug:%s", d);
-                    pa_xfree(d);
-                    d = t;
+                *ss = try_ss;
+                *map = device_table[i].map;
+                pa_assert(map->channels == ss->channels);
+                *dev = d;
+                if (config_description)
+                    *config_description = device_table[i].description;
+                if (config_name)
+                    *config_name = device_table[i].name;
 
-                    reformat = FALSE;
+                return pcm_handle;
+            }
 
-                    snd_pcm_close(pcm_handle);
-                    continue;
-                }
+            pa_xfree(d);
+        }
 
-                pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err));
-                snd_pcm_close(pcm_handle);
-                break;
+        if (direction > 0) {
+            if (!device_table[i+1].alsa_name) {
+                /* OK, so we are at the end of our list. Let's turn
+                 * back. */
+                direction = -1;
+            } else {
+                /* We are not at the end of the list, so let's simply
+                 * try the next entry */
+                i++;
             }
-
-            *ss = try_ss;
-            *map = device_table[i].map;
-            pa_assert(map->channels == ss->channels);
-            *dev = d;
-            return pcm_handle;
         }
 
-        pa_xfree(d);
+        if (direction < 0) {
+
+            if (device_table[i+1].alsa_name &&
+                device_table[i].map.channels == device_table[i+1].map.channels) {
+
+                /* OK, the next entry has the same number of channels,
+                 * let's try it */
+                i++;
+
+            } else {
+                /* Hmm, so the next entry does not have the same
+                 * number of channels, so let's go backwards until we
+                 * find the next entry with a differnt number of
+                 * channels */
+
+                for (i--; i >= 0; i--)
+                    if (device_table[i].map.channels != device_table[i+1].map.channels)
+                        break;
+
+                /* Hmm, there is no entry with a different number of
+                 * entries, then we're done */
+                if (i < 0)
+                    break;
+
+                /* OK, now lets find go back as long as we have the same number of channels */
+                for (; i > 0; i--)
+                    if (device_table[i].map.channels != device_table[i-1].map.channels)
+                        break;
+            }
+        }
     }
 
     /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
@@ -647,6 +729,11 @@ snd_pcm_t *pa_alsa_open_by_device_id(
     pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched);
     pa_xfree(d);
 
+    if (pcm_handle) {
+        *config_description = NULL;
+        *config_name = NULL;
+    }
+
     return pcm_handle;
 }
 
index 95bb983a85caa0d49f75b25c8ac0661907b05c2a..ce5f0eb6579e41d2c618047af1e2b29150d61d9d 100644 (file)
@@ -64,7 +64,9 @@ snd_pcm_t *pa_alsa_open_by_device_id(
         snd_pcm_uframes_t *period_size,
         snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
-        pa_bool_t *use_tsched);
+        pa_bool_t *use_tsched,
+        const char **config_name,
+        const char **config_description);
 
 snd_pcm_t *pa_alsa_open_by_device_string(
         const char *device,
index a3e818ddc4039aa582767e94ba32757b76e058ff..dfa20557220fa80af90700a13801f8c234e62134 100644 (file)
@@ -1253,6 +1253,7 @@ int pa__init(pa_module*m) {
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
     pa_usec_t usec;
     pa_sink_new_data data;
+    const char *profile_description = NULL, *profile_name = NULL;
 
     snd_pcm_info_alloca(&pcm_info);
 
@@ -1338,7 +1339,7 @@ int pa__init(pa_module*m) {
                       &ss, &map,
                       SND_PCM_STREAM_PLAYBACK,
                       &nfrags, &period_frames, tsched_frames,
-                      &b, &d)))
+                      &b, &d, &profile_description, &profile_name)))
 
             goto fail;
 
@@ -1358,6 +1359,9 @@ int pa__init(pa_module*m) {
     pa_assert(u->device_name);
     pa_log_info("Successfully opened device %s.", u->device_name);
 
+    if (profile_description)
+        pa_log_info("Selected configuration '%s' (%s).", profile_description, profile_name);
+
     if (use_mmap && !b) {
         pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
         u->use_mmap = use_mmap = FALSE;
@@ -1441,6 +1445,11 @@ int pa__init(pa_module*m) {
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
 
+    if (profile_name)
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, profile_name);
+    if (profile_description)
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile_description);
+
     u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
     pa_xfree(name_buf);
index 901db01f88db396cd53a54dc4e99fca571c85630..f89b6e2e59fa65819e24e1e463fe1f20f3792123 100644 (file)
@@ -1087,6 +1087,7 @@ int pa__init(pa_module*m) {
     pa_bool_t namereg_fail;
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
     pa_source_new_data data;
+    const char *profile_description = NULL, *profile_name = NULL;
 
     snd_pcm_info_alloca(&pcm_info);
 
@@ -1167,7 +1168,7 @@ int pa__init(pa_module*m) {
                       &ss, &map,
                       SND_PCM_STREAM_CAPTURE,
                       &nfrags, &period_frames, tsched_frames,
-                      &b, &d)))
+                      &b, &d, &profile_description, &profile_name)))
             goto fail;
 
     } else {
@@ -1185,6 +1186,9 @@ int pa__init(pa_module*m) {
     pa_assert(u->device_name);
     pa_log_info("Successfully opened device %s.", u->device_name);
 
+    if (profile_description)
+        pa_log_info("Selected configuration '%s' (%s).", profile_description, profile_name);
+
     if (use_mmap && !b) {
         pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
         u->use_mmap = use_mmap = FALSE;
@@ -1268,6 +1272,11 @@ int pa__init(pa_module*m) {
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
 
+    if (profile_name)
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, profile_name);
+    if (profile_description)
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile_description);
+
     u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
     pa_source_new_data_done(&data);
     pa_xfree(name_buf);
index 5d65ff3cc838a643ec3ab672fafd40211c77298c..77f0399c10a32dacf141500cb95624f33210b9ca 100644 (file)
@@ -75,8 +75,10 @@ PA_C_DECL_BEGIN
  *    device.connector              isa, pci, usb, firewire, bluetooth
  *    device.access_mode            mmap, mmap_rewrite, serial
  *    device.master_device
- *    device.bufferin.buffer_size
- *    device.bufferin.fragment_size
+ *    device.buffering.buffer_size
+ *    device.buffering.fragment_size
+ *    device.profile.name           analog-stereo, analog-surround-40, iec958-stereo, ...
+ *    device.profile.description    "Analog Stereo", ...
  */
 #define PA_PROP_MEDIA_NAME                     "media.name"
 #define PA_PROP_MEDIA_TITLE                    "media.title"
@@ -124,6 +126,8 @@ PA_C_DECL_BEGIN
 #define PA_PROP_DEVICE_MASTER_DEVICE           "device.master_device"
 #define PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE   "device.buffering.buffer_size"
 #define PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE "device.buffering.fragment_size"
+#define PA_PROP_DEVICE_PROFILE_NAME            "device.profile.name"
+#define PA_PROP_DEVICE_PROFILE_DESCRIPTION     "device.profile.description"
 
 /** A property list object. Basically a dictionary with UTF-8 strings
  * as keys and arbitrary data as values. \since 0.9.11 */