mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
alsa-pcm: bind_ctl: add better ctl name matching
For matching kctl without the numid you need to specify interface, device, subdevice, name and index. So the current implementation can only match kctls on IFACE_PCM, device 0, subdevice 0 and index 0. Instead of adding all these matching parameters this commit fetches all kctls attached to the audio card and match on the first occurred kctl with matching name. This should be sufficient for audio cards with unique kctl names. When non unique names are needed, more kctl matching parameters needs to be added.
This commit is contained in:
parent
8a271a87b7
commit
96f35e15a0
1 changed files with 80 additions and 26 deletions
|
|
@ -693,6 +693,85 @@ static void bind_ctl_event(struct spa_source *source)
|
|||
}
|
||||
}
|
||||
|
||||
static void fetch_bind_ctls(struct state *state)
|
||||
{
|
||||
snd_ctl_elem_list_t* element_list;
|
||||
unsigned int elem_count = 0;
|
||||
int err;
|
||||
|
||||
if (!state->num_bind_ctls)
|
||||
return;
|
||||
|
||||
snd_ctl_elem_list_alloca(&element_list);
|
||||
|
||||
/* Get number of elements */
|
||||
err = snd_ctl_elem_list(state->ctl, element_list);
|
||||
if (SPA_UNLIKELY(err < 0)) {
|
||||
spa_log_warn(state->log, "Couldn't get elem list count. Error: %s",
|
||||
snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
elem_count = snd_ctl_elem_list_get_count(element_list);
|
||||
err = snd_ctl_elem_list_alloc_space(element_list, elem_count);
|
||||
if (SPA_UNLIKELY(err < 0)) {
|
||||
spa_log_error(state->log, "Couldn't allocate elem_list space. Error: %s",
|
||||
snd_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get identifiers */
|
||||
err = snd_ctl_elem_list(state->ctl, element_list);
|
||||
if (SPA_UNLIKELY(err < 0)) {
|
||||
spa_log_warn(state->log, "Couldn't get elem list. Error: %s",
|
||||
snd_strerror(err));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < state->num_bind_ctls; i++) {
|
||||
unsigned int numid = 0;
|
||||
|
||||
for (unsigned int j = 0; i < elem_count; j++) {
|
||||
const char* element_name = snd_ctl_elem_list_get_name(element_list, j);
|
||||
|
||||
if (!strcmp(element_name, state->bound_ctls[i].name)) {
|
||||
numid = snd_ctl_elem_list_get_numid(element_list, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* zero = invalid numid */
|
||||
if (SPA_UNLIKELY(!numid)) {
|
||||
spa_log_warn(state->log, "Didn't find ctl: '%s', count: %u",
|
||||
state->bound_ctls[i].name, elem_count);
|
||||
continue;
|
||||
}
|
||||
|
||||
snd_ctl_elem_info_malloc(&state->bound_ctls[i].info);
|
||||
snd_ctl_elem_info_set_numid(state->bound_ctls[i].info, numid);
|
||||
|
||||
err = snd_ctl_elem_info(state->ctl, state->bound_ctls[i].info);
|
||||
if (SPA_UNLIKELY(err < 0)) {
|
||||
spa_log_warn(state->log, "Could not read elem info for '%s': %s",
|
||||
state->bound_ctls[i].name, snd_strerror(err));
|
||||
|
||||
snd_ctl_elem_info_free(state->bound_ctls[i].info);
|
||||
state->bound_ctls[i].info = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
snd_ctl_elem_value_malloc(&state->bound_ctls[i].value);
|
||||
snd_ctl_elem_value_set_numid(state->bound_ctls[i].value, numid);
|
||||
|
||||
spa_log_debug(state->log, "Binding ctl for '%s'",
|
||||
snd_ctl_elem_info_get_name(state->bound_ctls[i].info));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
snd_ctl_elem_list_free_space(element_list);
|
||||
}
|
||||
|
||||
static void bind_ctls_for_params(struct state *state)
|
||||
{
|
||||
struct pollfd pfds[16];
|
||||
|
|
@ -737,32 +816,7 @@ static void bind_ctls_for_params(struct state *state)
|
|||
spa_loop_add_source(state->main_loop, &state->ctl_sources[i]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < state->num_bind_ctls; i++) {
|
||||
snd_ctl_elem_id_t *id;
|
||||
|
||||
snd_ctl_elem_id_alloca(&id);
|
||||
snd_ctl_elem_id_set_name(id, state->bound_ctls[i].name);
|
||||
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
|
||||
|
||||
snd_ctl_elem_info_malloc(&state->bound_ctls[i].info);
|
||||
snd_ctl_elem_info_set_id(state->bound_ctls[i].info, id);
|
||||
|
||||
err = snd_ctl_elem_info(state->ctl, state->bound_ctls[i].info);
|
||||
if (err < 0) {
|
||||
spa_log_warn(state->log, "Could not read elem info for '%s': %s",
|
||||
state->bound_ctls[i].name, snd_strerror(err));
|
||||
|
||||
snd_ctl_elem_info_free(state->bound_ctls[i].info);
|
||||
state->bound_ctls[i].info = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
snd_ctl_elem_value_malloc(&state->bound_ctls[i].value);
|
||||
snd_ctl_elem_value_set_id(state->bound_ctls[i].value, id);
|
||||
|
||||
spa_log_debug(state->log, "Binding ctl for '%s'",
|
||||
snd_ctl_elem_info_get_name(state->bound_ctls[i].info));
|
||||
}
|
||||
fetch_bind_ctls(state);
|
||||
}
|
||||
|
||||
int spa_alsa_init(struct state *state, const struct spa_dict *info)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue