diff options
| author | Lennart Poettering <lennart@poettering.net> | 2009-01-15 23:46:42 +0100 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2009-01-15 23:46:42 +0100 | 
| commit | 4d4956ea2f8df5f770f2137d8576afc6e5f161dd (patch) | |
| tree | 57b735d18eaf40647e181c167183283208a6cebf | |
| parent | 33c22b01022b0450aee011ddd9d6d2b19da74191 (diff) | |
Add SPDIF/HDMI ALSA devices and device descriptions to device search table
| -rw-r--r-- | src/modules/alsa/alsa-util.c | 223 | ||||
| -rw-r--r-- | src/modules/alsa/alsa-util.h | 4 | ||||
| -rw-r--r-- | src/modules/alsa/module-alsa-sink.c | 11 | ||||
| -rw-r--r-- | src/modules/alsa/module-alsa-source.c | 11 | ||||
| -rw-r--r-- | src/pulse/proplist.h | 8 | 
5 files changed, 184 insertions, 73 deletions
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index ff3af19d..871471f1 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -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;  } diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h index 95bb983a..ce5f0eb6 100644 --- a/src/modules/alsa/alsa-util.h +++ b/src/modules/alsa/alsa-util.h @@ -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, diff --git a/src/modules/alsa/module-alsa-sink.c b/src/modules/alsa/module-alsa-sink.c index a3e818dd..dfa20557 100644 --- a/src/modules/alsa/module-alsa-sink.c +++ b/src/modules/alsa/module-alsa-sink.c @@ -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); diff --git a/src/modules/alsa/module-alsa-source.c b/src/modules/alsa/module-alsa-source.c index 901db01f..f89b6e2e 100644 --- a/src/modules/alsa/module-alsa-source.c +++ b/src/modules/alsa/module-alsa-source.c @@ -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); diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h index 5d65ff3c..77f0399c 100644 --- a/src/pulse/proplist.h +++ b/src/pulse/proplist.h @@ -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 */  | 
