Add SPDIF/HDMI ALSA devices and device descriptions to device search table

This commit is contained in:
Lennart Poettering 2009-01-15 23:46:42 +01:00
parent 33c22b0102
commit 4d4956ea2f
5 changed files with 189 additions and 78 deletions

View 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);
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);
/* OK, so we iterated backwards, and now are at the
* beginning of our list. */
d = pa_sprintf_malloc("%s:%s", device_table[i].alsa_name, dev_id);
break;
reformat = FALSE;
for (;;) {
pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
} else if (!device_table[i].name) {
pa_assert(direction == 1);
/* 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 */
/* OK, so we are at the end of our list. at iterated
* forwards. */
i--;
direction = -1;
}
if ((direction > 0) == !channel_map_superset(&device_table[i].map, map))
continue;
d = pa_sprintf_malloc("%s:%s", device_table[i].name, dev_id);
reformat = FALSE;
for (;;) {
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 we enable nonblock mode afterwards via
* snd_pcm_nonblock(). Also see
* http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
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;
}
try_ss.channels = device_table[i].map.channels;
try_ss.rate = ss->rate;
try_ss.format = ss->format;
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 ((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 (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
char *t;
try_ss.channels = device_table[i].map.channels;
try_ss.rate = ss->rate;
try_ss.format = ss->format;
t = pa_sprintf_malloc("plug:%s", d);
pa_xfree(d);
d = t;
if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) {
reformat = FALSE;
if (!reformat) {
reformat = TRUE;
snd_pcm_close(pcm_handle);
continue;
}
if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
char *t;
t = pa_sprintf_malloc("plug:%s", d);
pa_xfree(d);
d = t;
reformat = FALSE;
snd_pcm_close(pcm_handle);
continue;
}
pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err));
snd_pcm_close(pcm_handle);
continue;
break;
}
pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err));
snd_pcm_close(pcm_handle);
break;
*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;
return pcm_handle;
}
*ss = try_ss;
*map = device_table[i].map;
pa_assert(map->channels == ss->channels);
*dev = d;
return pcm_handle;
pa_xfree(d);
}
pa_xfree(d);
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++;
}
}
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;
}