summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor V. Kovalenko <igor.v.kovalenko@gmail.com>2023-02-22 01:19:24 +0300
committerPulseAudio Marge Bot <pulseaudio-maintainers@lists.freedesktop.org>2023-02-25 12:00:38 +0000
commitaed52c507f345d0b5c4cd2b1d2c58dae2d904b53 (patch)
tree7f7fc3891f6cb6e11837a74ee94e587959fda15c
parentb8e2198d34da2e085b469d7e3a472cbdaec9e5b8 (diff)
downloadpulseaudio-aed52c507f345d0b5c4cd2b1d2c58dae2d904b53.tar.gz
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>
-rw-r--r--src/modules/alsa/alsa-mixer.c2
-rw-r--r--src/modules/alsa/alsa-sink.c14
-rw-r--r--src/modules/alsa/alsa-source.c8
-rw-r--r--src/modules/alsa/alsa-ucm.c2
-rw-r--r--src/modules/alsa/alsa-util.c24
-rw-r--r--src/modules/alsa/alsa-util.h8
6 files changed, 46 insertions, 12 deletions
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 49c39687c..c272e392b 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -5074,7 +5074,7 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m,
handle = pa_alsa_open_by_template(
m->device_strings, dev_id, NULL, &try_ss,
&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) {
char buf[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_log_debug("Channel map for mapping '%s' permanently changed to '%s'", m->name,
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index b249df680..ca22f195f 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -2527,7 +2527,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
&period_frames, &buffer_frames, tsched_frames,
- &b, &d, mapping)))
+ &b, &d,
+ &u->supported_formats, &u->supported_rates,
+ mapping)))
goto fail;
} 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,
SND_PCM_STREAM_PLAYBACK,
&period_frames, &buffer_frames, tsched_frames,
- &b, &d, profile_set, &mapping)))
+ &b, &d,
+ &u->supported_formats, &u->supported_rates,
+ profile_set, &mapping)))
goto fail;
} else {
@@ -2552,7 +2556,9 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
&period_frames, &buffer_frames, tsched_frames,
- &b, &d, false)))
+ &b, &d,
+ &u->supported_formats, &u->supported_rates,
+ false)))
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->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
if (!u->supported_formats) {
pa_log_error("Failed to find any supported sample formats.");
goto fail;
}
- u->supported_rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
if (!u->supported_rates) {
pa_log_error("Failed to find any supported sample rates.");
goto fail;
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index ef8b12c32..d88c47f1f 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -2218,7 +2218,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&period_frames, &buffer_frames, tsched_frames,
- &b, &d, mapping)))
+ &b, &d, &u->supported_formats, &u->supported_rates, mapping)))
goto fail;
} 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,
SND_PCM_STREAM_CAPTURE,
&period_frames, &buffer_frames, tsched_frames,
- &b, &d, profile_set, &mapping)))
+ &b, &d, &u->supported_formats, &u->supported_rates, profile_set, &mapping)))
goto fail;
} else {
@@ -2243,7 +2243,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&period_frames, &buffer_frames, tsched_frames,
- &b, &d, false)))
+ &b, &d, &u->supported_formats, &u->supported_rates, false)))
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->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
if (!u->supported_formats) {
pa_log_error("Failed to find any supported sample formats.");
goto fail;
}
- u->supported_rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
if (!u->supported_rates) {
pa_log_error("Failed to find any supported sample rates.");
goto fail;
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index e75756f53..744e7aae1 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -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;
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 (!exact_channels)
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index fd30f18bd..b631c870c 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -523,6 +523,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
snd_pcm_uframes_t tsched_size,
bool *use_mmap,
bool *use_tsched,
+ pa_sample_format_t **query_supported_formats,
+ unsigned int **query_supported_rates,
pa_alsa_profile_set *ps,
pa_alsa_mapping **mapping) {
@@ -561,6 +563,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
tsched_size,
use_mmap,
use_tsched,
+ query_supported_formats,
+ query_supported_rates,
m);
if (pcm_handle) {
@@ -588,6 +592,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
tsched_size,
use_mmap,
use_tsched,
+ query_supported_formats,
+ query_supported_rates,
m);
if (pcm_handle) {
@@ -612,6 +618,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
tsched_size,
use_mmap,
use_tsched,
+ query_supported_formats,
+ query_supported_rates,
false);
pa_xfree(d);
@@ -632,6 +640,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
snd_pcm_uframes_t tsched_size,
bool *use_mmap,
bool *use_tsched,
+ pa_sample_format_t **query_supported_formats,
+ unsigned int **query_supported_rates,
pa_alsa_mapping *m) {
snd_pcm_t *pcm_handle;
@@ -661,6 +671,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_mapping(
tsched_size,
use_mmap,
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 */);
if (!pcm_handle)
@@ -684,6 +696,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
snd_pcm_uframes_t tsched_size,
bool *use_mmap,
bool *use_tsched,
+ pa_sample_format_t **query_supported_formats,
+ unsigned int **query_supported_rates,
bool require_exact_channel_number) {
int err;
@@ -711,6 +725,12 @@ snd_pcm_t *pa_alsa_open_by_device_string(
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(
pcm_handle,
ss,
@@ -784,6 +804,8 @@ snd_pcm_t *pa_alsa_open_by_template(
snd_pcm_uframes_t tsched_size,
bool *use_mmap,
bool *use_tsched,
+ pa_sample_format_t **query_supported_formats,
+ unsigned int **query_supported_rates,
bool require_exact_channel_number) {
snd_pcm_t *pcm_handle;
@@ -805,6 +827,8 @@ snd_pcm_t *pa_alsa_open_by_template(
tsched_size,
use_mmap,
use_tsched,
+ query_supported_formats,
+ query_supported_rates,
require_exact_channel_number);
pa_xfree(d);
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 2eed3eac3..c65801104 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -67,6 +67,8 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
snd_pcm_uframes_t tsched_size,
bool *use_mmap, /* 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_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,
bool *use_mmap, /* 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);
/* Opens the explicit ALSA device */
@@ -96,6 +100,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
snd_pcm_uframes_t tsched_size,
bool *use_mmap, /* 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);
/* 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,
bool *use_mmap, /* 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);
void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm);