alsa: Use hw:X for accessing card ctl

In ACP mode, we might be accessing front:0 as the PCM, and using that
string to generate the ctl device name does not make sense. In
PulseAudio, we used the card index to generate a hw:X string, and we
replicate that here.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4028
This commit is contained in:
Arun Raghavan 2024-05-27 17:21:36 +03:00
parent 5be2f5e096
commit 2f9a5e0694

View file

@ -657,21 +657,6 @@ static void fill_device_name(struct state *state, const char *params, char devic
state->props.device, params ? params : "");
}
static void device_name_to_card_name(const char *device_name, char *card_name, size_t card_len)
{
size_t card_name_len = strcspn(device_name, ",");
snprintf(card_name, card_len, "%.*s", (int) card_name_len, device_name);
}
static void fill_card_name(struct state *state, const char *params, char *card_name, size_t len)
{
char device_name[256];
size_t max_len = SPA_MIN(len, sizeof(device_name));
fill_device_name(state, params, device_name, max_len);
device_name_to_card_name(device_name, card_name, max_len);
}
static void bind_ctl_event(struct spa_source *source)
{
struct state *state = source->data;
@ -830,6 +815,23 @@ cleanup:
snd_ctl_elem_list_free_space(element_list);
}
int open_card_ctl(struct state *state)
{
int err;
char card_name[256];
snprintf(card_name, sizeof(card_name), "hw:%d", state->card_index);
err = snd_ctl_open(&state->ctl, card_name, SND_CTL_NONBLOCK);
if (err < 0) {
spa_log_info(state->log, "%s could not find ctl card: %s",
card_name, snd_strerror(err));
return err;
}
return 0;
}
static void bind_ctls_for_params(struct state *state)
{
int err;
@ -838,17 +840,9 @@ static void bind_ctls_for_params(struct state *state)
return;
if (!state->ctl) {
char card_name[256];
fill_card_name(state, NULL, card_name, sizeof(card_name));
err = snd_ctl_open(&state->ctl, card_name, SND_CTL_NONBLOCK);
if (err < 0) {
spa_log_info(state->log, "%s could not find ctl card: %s",
card_name, snd_strerror(err));
state->ctl = NULL;
err = open_card_ctl(state);
if (err < 0)
return;
}
}
state->ctl_n_fds = snd_ctl_poll_descriptors_count(state->ctl);
@ -1003,7 +997,7 @@ int spa_alsa_clear(struct state *state)
return err;
}
static int probe_pitch_ctl(struct state *state, const char* device_name)
static int probe_pitch_ctl(struct state *state)
{
snd_ctl_elem_id_t *id;
/* TODO: Add configuration params for the control name and units */
@ -1017,16 +1011,10 @@ static int probe_pitch_ctl(struct state *state, const char* device_name)
snd_lib_error_set_handler(silence_error_handler);
if (!state->ctl) {
char card_name[256];
device_name_to_card_name(device_name, card_name, sizeof(card_name));
err = snd_ctl_open(&state->ctl, card_name, SND_CTL_NONBLOCK);
if (err < 0) {
spa_log_info(state->log, "%s could not find ctl card: %s",
card_name, snd_strerror(err));
state->ctl = NULL;
err = open_card_ctl(state);
if (err < 0)
goto error;
}
opened = true;
}
@ -1039,8 +1027,8 @@ static int probe_pitch_ctl(struct state *state, const char* device_name)
err = snd_ctl_elem_read(state->ctl, state->pitch_elem);
if (err < 0) {
spa_log_debug(state->log, "%s: did not find ctl %s: %s",
device_name, elem_name, snd_strerror(err));
spa_log_debug(state->log, "%s: did not find ctl: %s",
elem_name, snd_strerror(err));
snd_ctl_elem_value_free(state->pitch_elem);
state->pitch_elem = NULL;
@ -1057,7 +1045,7 @@ static int probe_pitch_ctl(struct state *state, const char* device_name)
CHECK(snd_ctl_elem_write(state->ctl, state->pitch_elem), "snd_ctl_elem_write");
state->last_rate = 1.0;
spa_log_info(state->log, "%s: found ctl %s", device_name, elem_name);
spa_log_info(state->log, "found ctl %s", elem_name);
err = 0;
error:
snd_lib_error_set_handler(NULL);
@ -1124,7 +1112,7 @@ int spa_alsa_open(struct state *state, const char *params)
state->sample_count = 0;
state->sample_time = 0;
probe_pitch_ctl(state, device_name);
probe_pitch_ctl(state);
return 0;