mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
alsa-util: Perform format and rate detection before setting HW params
Perform detection of supported sample format and rates just after device is opened, before `snd_pcm_hw_params()` is called for the first time. This fixes a problem where device restricts available sample rates after HW params are set preventing sample rate detection (seen with UAC2 devices and kernel 6.1.9) Bug: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1414 Bug: https://github.com/alsa-project/alsa-lib/issues/119 Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/782>
This commit is contained in:
parent
b8e2198d34
commit
aed52c507f
6 changed files with 46 additions and 12 deletions
|
|
@ -5074,7 +5074,7 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m,
|
||||||
handle = pa_alsa_open_by_template(
|
handle = pa_alsa_open_by_template(
|
||||||
m->device_strings, dev_id, NULL, &try_ss,
|
m->device_strings, dev_id, NULL, &try_ss,
|
||||||
&try_map, mode, &try_period_size,
|
&try_map, mode, &try_period_size,
|
||||||
&try_buffer_size, 0, NULL, NULL, exact_channels);
|
&try_buffer_size, 0, NULL, NULL, NULL, NULL, exact_channels);
|
||||||
if (handle && !exact_channels && m->channel_map.channels != try_map.channels) {
|
if (handle && !exact_channels && m->channel_map.channels != try_map.channels) {
|
||||||
char buf[PA_CHANNEL_MAP_SNPRINT_MAX];
|
char buf[PA_CHANNEL_MAP_SNPRINT_MAX];
|
||||||
pa_log_debug("Channel map for mapping '%s' permanently changed to '%s'", m->name,
|
pa_log_debug("Channel map for mapping '%s' permanently changed to '%s'", m->name,
|
||||||
|
|
|
||||||
|
|
@ -2527,7 +2527,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||||
&ss, &map,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_PLAYBACK,
|
SND_PCM_STREAM_PLAYBACK,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, mapping)))
|
&b, &d,
|
||||||
|
&u->supported_formats, &u->supported_rates,
|
||||||
|
mapping)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
|
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
|
||||||
|
|
@ -2541,7 +2543,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||||
&ss, &map,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_PLAYBACK,
|
SND_PCM_STREAM_PLAYBACK,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, profile_set, &mapping)))
|
&b, &d,
|
||||||
|
&u->supported_formats, &u->supported_rates,
|
||||||
|
profile_set, &mapping)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2552,7 +2556,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||||
&ss, &map,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_PLAYBACK,
|
SND_PCM_STREAM_PLAYBACK,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, false)))
|
&b, &d,
|
||||||
|
&u->supported_formats, &u->supported_rates,
|
||||||
|
false)))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2598,13 +2604,11 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
||||||
|
|
||||||
u->verified_sample_spec = ss;
|
u->verified_sample_spec = ss;
|
||||||
|
|
||||||
u->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
|
|
||||||
if (!u->supported_formats) {
|
if (!u->supported_formats) {
|
||||||
pa_log_error("Failed to find any supported sample formats.");
|
pa_log_error("Failed to find any supported sample formats.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->supported_rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
|
|
||||||
if (!u->supported_rates) {
|
if (!u->supported_rates) {
|
||||||
pa_log_error("Failed to find any supported sample rates.");
|
pa_log_error("Failed to find any supported sample rates.");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -2218,7 +2218,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
&ss, &map,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_CAPTURE,
|
SND_PCM_STREAM_CAPTURE,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, mapping)))
|
&b, &d, &u->supported_formats, &u->supported_rates, mapping)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
|
} else if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
|
||||||
|
|
@ -2232,7 +2232,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
&ss, &map,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_CAPTURE,
|
SND_PCM_STREAM_CAPTURE,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, profile_set, &mapping)))
|
&b, &d, &u->supported_formats, &u->supported_rates, profile_set, &mapping)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2243,7 +2243,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
&ss, &map,
|
&ss, &map,
|
||||||
SND_PCM_STREAM_CAPTURE,
|
SND_PCM_STREAM_CAPTURE,
|
||||||
&period_frames, &buffer_frames, tsched_frames,
|
&period_frames, &buffer_frames, tsched_frames,
|
||||||
&b, &d, false)))
|
&b, &d, &u->supported_formats, &u->supported_rates, false)))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2279,13 +2279,11 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
||||||
|
|
||||||
u->verified_sample_spec = ss;
|
u->verified_sample_spec = ss;
|
||||||
|
|
||||||
u->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
|
|
||||||
if (!u->supported_formats) {
|
if (!u->supported_formats) {
|
||||||
pa_log_error("Failed to find any supported sample formats.");
|
pa_log_error("Failed to find any supported sample formats.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->supported_rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
|
|
||||||
if (!u->supported_rates) {
|
if (!u->supported_rates) {
|
||||||
pa_log_error("Failed to find any supported sample rates.");
|
pa_log_error("Failed to find any supported sample rates.");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -2026,7 +2026,7 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m,
|
||||||
try_buffer_size = ucm->core->default_n_fragments * try_period_size;
|
try_buffer_size = ucm->core->default_n_fragments * try_period_size;
|
||||||
|
|
||||||
pcm = pa_alsa_open_by_device_string(m->device_strings[0], NULL, &try_ss,
|
pcm = pa_alsa_open_by_device_string(m->device_strings[0], NULL, &try_ss,
|
||||||
&try_map, mode, &try_period_size, &try_buffer_size, 0, NULL, NULL, exact_channels);
|
&try_map, mode, &try_period_size, &try_buffer_size, 0, NULL, NULL, NULL, NULL, exact_channels);
|
||||||
|
|
||||||
if (pcm) {
|
if (pcm) {
|
||||||
if (!exact_channels)
|
if (!exact_channels)
|
||||||
|
|
|
||||||
|
|
@ -523,6 +523,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap,
|
bool *use_mmap,
|
||||||
bool *use_tsched,
|
bool *use_tsched,
|
||||||
|
pa_sample_format_t **query_supported_formats,
|
||||||
|
unsigned int **query_supported_rates,
|
||||||
pa_alsa_profile_set *ps,
|
pa_alsa_profile_set *ps,
|
||||||
pa_alsa_mapping **mapping) {
|
pa_alsa_mapping **mapping) {
|
||||||
|
|
||||||
|
|
@ -561,6 +563,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
|
query_supported_formats,
|
||||||
|
query_supported_rates,
|
||||||
m);
|
m);
|
||||||
|
|
||||||
if (pcm_handle) {
|
if (pcm_handle) {
|
||||||
|
|
@ -588,6 +592,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
|
query_supported_formats,
|
||||||
|
query_supported_rates,
|
||||||
m);
|
m);
|
||||||
|
|
||||||
if (pcm_handle) {
|
if (pcm_handle) {
|
||||||
|
|
@ -612,6 +618,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
|
query_supported_formats,
|
||||||
|
query_supported_rates,
|
||||||
false);
|
false);
|
||||||
pa_xfree(d);
|
pa_xfree(d);
|
||||||
|
|
||||||
|
|
@ -632,6 +640,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap,
|
bool *use_mmap,
|
||||||
bool *use_tsched,
|
bool *use_tsched,
|
||||||
|
pa_sample_format_t **query_supported_formats,
|
||||||
|
unsigned int **query_supported_rates,
|
||||||
pa_alsa_mapping *m) {
|
pa_alsa_mapping *m) {
|
||||||
|
|
||||||
snd_pcm_t *pcm_handle;
|
snd_pcm_t *pcm_handle;
|
||||||
|
|
@ -661,6 +671,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
|
query_supported_formats,
|
||||||
|
query_supported_rates,
|
||||||
pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
|
pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
|
||||||
|
|
||||||
if (!pcm_handle)
|
if (!pcm_handle)
|
||||||
|
|
@ -684,6 +696,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap,
|
bool *use_mmap,
|
||||||
bool *use_tsched,
|
bool *use_tsched,
|
||||||
|
pa_sample_format_t **query_supported_formats,
|
||||||
|
unsigned int **query_supported_rates,
|
||||||
bool require_exact_channel_number) {
|
bool require_exact_channel_number) {
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
|
|
@ -711,6 +725,12 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
||||||
|
|
||||||
pa_log_debug("Managed to open %s", d);
|
pa_log_debug("Managed to open %s", d);
|
||||||
|
|
||||||
|
if (query_supported_formats)
|
||||||
|
*query_supported_formats = pa_alsa_get_supported_formats(pcm_handle, ss->format);
|
||||||
|
|
||||||
|
if (query_supported_rates)
|
||||||
|
*query_supported_rates = pa_alsa_get_supported_rates(pcm_handle, ss->rate);
|
||||||
|
|
||||||
if ((err = pa_alsa_set_hw_params(
|
if ((err = pa_alsa_set_hw_params(
|
||||||
pcm_handle,
|
pcm_handle,
|
||||||
ss,
|
ss,
|
||||||
|
|
@ -784,6 +804,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap,
|
bool *use_mmap,
|
||||||
bool *use_tsched,
|
bool *use_tsched,
|
||||||
|
pa_sample_format_t **query_supported_formats,
|
||||||
|
unsigned int **query_supported_rates,
|
||||||
bool require_exact_channel_number) {
|
bool require_exact_channel_number) {
|
||||||
|
|
||||||
snd_pcm_t *pcm_handle;
|
snd_pcm_t *pcm_handle;
|
||||||
|
|
@ -805,6 +827,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
||||||
tsched_size,
|
tsched_size,
|
||||||
use_mmap,
|
use_mmap,
|
||||||
use_tsched,
|
use_tsched,
|
||||||
|
query_supported_formats,
|
||||||
|
query_supported_rates,
|
||||||
require_exact_channel_number);
|
require_exact_channel_number);
|
||||||
|
|
||||||
pa_xfree(d);
|
pa_xfree(d);
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap, /* modified at return */
|
bool *use_mmap, /* modified at return */
|
||||||
bool *use_tsched, /* modified at return */
|
bool *use_tsched, /* modified at return */
|
||||||
|
pa_sample_format_t **query_supported_formats, /* modified at return */
|
||||||
|
unsigned int **query_supported_rates, /* modified at return */
|
||||||
pa_alsa_profile_set *ps,
|
pa_alsa_profile_set *ps,
|
||||||
pa_alsa_mapping **mapping); /* modified at return */
|
pa_alsa_mapping **mapping); /* modified at return */
|
||||||
|
|
||||||
|
|
@ -82,6 +84,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap, /* modified at return */
|
bool *use_mmap, /* modified at return */
|
||||||
bool *use_tsched, /* modified at return */
|
bool *use_tsched, /* modified at return */
|
||||||
|
pa_sample_format_t **query_supported_formats, /* modified at return */
|
||||||
|
unsigned int **query_supported_rates, /* modified at return */
|
||||||
pa_alsa_mapping *mapping);
|
pa_alsa_mapping *mapping);
|
||||||
|
|
||||||
/* Opens the explicit ALSA device */
|
/* Opens the explicit ALSA device */
|
||||||
|
|
@ -96,6 +100,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap, /* modified at return */
|
bool *use_mmap, /* modified at return */
|
||||||
bool *use_tsched, /* modified at return */
|
bool *use_tsched, /* modified at return */
|
||||||
|
pa_sample_format_t **query_supported_formats, /* modified at return */
|
||||||
|
unsigned int **query_supported_rates, /* modified at return */
|
||||||
bool require_exact_channel_number);
|
bool require_exact_channel_number);
|
||||||
|
|
||||||
/* Opens the explicit ALSA device with a fallback list */
|
/* Opens the explicit ALSA device with a fallback list */
|
||||||
|
|
@ -111,6 +117,8 @@ snd_pcm_t *pa_alsa_open_by_template(
|
||||||
snd_pcm_uframes_t tsched_size,
|
snd_pcm_uframes_t tsched_size,
|
||||||
bool *use_mmap, /* modified at return */
|
bool *use_mmap, /* modified at return */
|
||||||
bool *use_tsched, /* modified at return */
|
bool *use_tsched, /* modified at return */
|
||||||
|
pa_sample_format_t **query_supported_formats, /* modified at return */
|
||||||
|
unsigned int **query_supported_rates, /* modified at return */
|
||||||
bool require_exact_channel_number);
|
bool require_exact_channel_number);
|
||||||
|
|
||||||
void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm);
|
void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue