mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05: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)
This commit is contained in:
parent
43770c533c
commit
96ed03e1fc
6 changed files with 69 additions and 5 deletions
|
|
@ -362,7 +362,7 @@ static int add_pro_profile(pa_card *impl, uint32_t index)
|
||||||
devstr, NULL, &m->sample_spec,
|
devstr, NULL, &m->sample_spec,
|
||||||
&m->channel_map, SND_PCM_STREAM_PLAYBACK,
|
&m->channel_map, SND_PCM_STREAM_PLAYBACK,
|
||||||
&try_period_size, &try_buffer_size,
|
&try_period_size, &try_buffer_size,
|
||||||
0, NULL, NULL, false))) {
|
0, NULL, NULL, NULL, NULL, false))) {
|
||||||
pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
|
pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
|
||||||
pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index);
|
pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index);
|
||||||
pa_alsa_close(&m->output_pcm);
|
pa_alsa_close(&m->output_pcm);
|
||||||
|
|
@ -392,7 +392,7 @@ static int add_pro_profile(pa_card *impl, uint32_t index)
|
||||||
devstr, NULL, &m->sample_spec,
|
devstr, NULL, &m->sample_spec,
|
||||||
&m->channel_map, SND_PCM_STREAM_CAPTURE,
|
&m->channel_map, SND_PCM_STREAM_CAPTURE,
|
||||||
&try_period_size, &try_buffer_size,
|
&try_period_size, &try_buffer_size,
|
||||||
0, NULL, NULL, false))) {
|
0, NULL, NULL, NULL, NULL, false))) {
|
||||||
pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
|
pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
|
||||||
pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index);
|
pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index);
|
||||||
pa_alsa_close(&m->input_pcm);
|
pa_alsa_close(&m->input_pcm);
|
||||||
|
|
|
||||||
|
|
@ -5012,7 +5012,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,
|
||||||
|
|
|
||||||
|
|
@ -2013,7 +2013,7 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_ucm_config *ucm, pa_alsa_mapping *m,
|
||||||
try_buffer_size = ucm->default_n_fragments * try_period_size;
|
try_buffer_size = ucm->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)
|
||||||
|
|
|
||||||
|
|
@ -505,6 +505,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) {
|
||||||
|
|
||||||
|
|
@ -543,6 +545,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) {
|
||||||
|
|
@ -570,6 +574,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) {
|
||||||
|
|
@ -594,6 +600,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);
|
||||||
|
|
||||||
|
|
@ -615,6 +623,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;
|
||||||
|
|
@ -644,6 +654,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)
|
||||||
|
|
@ -681,6 +693,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;
|
||||||
|
|
@ -708,6 +722,12 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
||||||
pa_log_info("ALSA device open '%s' %s: %p", d,
|
pa_log_info("ALSA device open '%s' %s: %p", d,
|
||||||
mode == SND_PCM_STREAM_CAPTURE ? "capture" : "playback", pcm_handle);
|
mode == SND_PCM_STREAM_CAPTURE ? "capture" : "playback", pcm_handle);
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
@ -781,6 +801,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;
|
||||||
|
|
@ -802,6 +824,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);
|
||||||
|
|
@ -1411,6 +1435,7 @@ char *pa_alsa_get_reserve_name(const char *device) {
|
||||||
|
|
||||||
return pa_sprintf_malloc("Audio%i", i);
|
return pa_sprintf_malloc("Audio%i", i);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void dump_supported_rates(unsigned int* values)
|
static void dump_supported_rates(unsigned int* values)
|
||||||
{
|
{
|
||||||
|
|
@ -1478,6 +1503,7 @@ unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_
|
||||||
rates[1] = 0;
|
rates[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dump_supported_rates(rates);
|
||||||
return rates;
|
return rates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1558,7 +1584,6 @@ pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_form
|
||||||
|
|
||||||
return formats;
|
return formats;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
|
bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
|
||||||
snd_pcm_info_t* info;
|
snd_pcm_info_t* info;
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,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 */
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -80,6 +82,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 */
|
||||||
|
|
@ -94,6 +98,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 */
|
||||||
|
|
@ -109,6 +115,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);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
||||||
|
|
@ -350,6 +350,37 @@ static inline void pa_xstrfreev(char **a) {
|
||||||
pa_xfreev((void**)a);
|
pa_xfreev((void**)a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t size;
|
||||||
|
char *ptr;
|
||||||
|
FILE *f;
|
||||||
|
} pa_strbuf;
|
||||||
|
|
||||||
|
static inline pa_strbuf *pa_strbuf_new(void)
|
||||||
|
{
|
||||||
|
pa_strbuf *s = pa_xnew0(pa_strbuf,1);
|
||||||
|
s->f = open_memstream(&s->ptr, &s->size);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PA_PRINTF_FUNC(2,3) inline size_t pa_strbuf_printf(pa_strbuf *sb, const char *format, ...)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
ret = fprintf(sb->f, format, args);
|
||||||
|
va_end(args);
|
||||||
|
return ret > 0 ? ret : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *pa_strbuf_to_string_free(pa_strbuf *sb)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
fclose(sb->f);
|
||||||
|
ptr = sb->ptr;
|
||||||
|
free(sb);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
#define pa_cstrerror strerror
|
#define pa_cstrerror strerror
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue