The syntax is ${CardIdByName:CARDNAME[#INDEX]}.
The CARDNAME is the ALSA's soundcard name (short form).
The INDEX is the instance (0 = first, 1 = second etc.).
Example: ${CardIdByName:HDA Intel PCH}
(which is identical to ${CardIdByName:HDA Intel PCH#0})
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
struct sequence_element *s;
char *cdev = NULL;
snd_ctl_t *ctl = NULL;
+ struct ctl_list *ctl_list;
int err = 0;
list_for_each(pos, seq) {
}
}
if (ctl == NULL) {
- err = uc_mgr_open_ctl(uc_mgr, &ctl, cdev);
+ err = uc_mgr_open_ctl(uc_mgr, &ctl_list, cdev, 1);
if (err < 0) {
uc_error("unable to open ctl device '%s'", cdev);
goto __fail;
}
+ ctl = ctl_list->ctl;
}
err = execute_cset(ctl, s->data.cset, s->type);
if (err < 0) {
char buf[40];
int err;
- ctl_list = uc_mgr_get_one_ctl(uc_mgr);
+ ctl_list = uc_mgr_get_master_ctl(uc_mgr);
if (ctl_list) {
id = snd_ctl_card_info_get_id(ctl_list->ctl_info);
snprintf(buf, sizeof(buf), "hw:%s", id);
/* get the card info */
static int get_card_info(snd_use_case_mgr_t *mgr,
const char *ctl_name,
- snd_ctl_t **_handle,
- snd_ctl_card_info_t *info)
+ snd_ctl_card_info_t **info)
{
- snd_ctl_t *handle;
+ struct ctl_list *ctl_list;
int err;
- *_handle = NULL;
-
- err = uc_mgr_open_ctl(mgr, &handle, ctl_name);
+ err = uc_mgr_open_ctl(mgr, &ctl_list, ctl_name, 0);
if (err < 0)
return err;
- err = snd_ctl_card_info(handle, info);
- if (err < 0) {
- uc_error("control hardware info (%s): %s", ctl_name, snd_strerror(err));
- } else {
- *_handle = handle;
- }
-
+ *info = ctl_list->ctl_info;
return err;
}
static int get_by_card_name(snd_use_case_mgr_t *mgr, const char *card_name)
{
int card, err;
- snd_ctl_t *ctl;
snd_ctl_card_info_t *info;
const char *_driver, *_name, *_long_name;
while (card >= 0) {
char name[32];
- /* mandatory - clear the list, keep the only one CTL device */
+ /* clear the list, keep the only one CTL device */
uc_mgr_free_ctl_list(mgr);
sprintf(name, "hw:%d", card);
- err = get_card_info(mgr, name, &ctl, info);
+ err = get_card_info(mgr, name, &info);
if (err == 0) {
_driver = snd_ctl_card_info_get_driver(info);
/* set the driver name and long name by the card ctl name */
static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name)
{
- snd_ctl_t *ctl;
snd_ctl_card_info_t *info;
int err;
snd_ctl_card_info_alloca(&info);
- err = get_card_info(mgr, ctl_name, &ctl, info);
+ err = get_card_info(mgr, ctl_name, &info);
if (err)
return err;
err = uc_mgr_get_substituted_value(uc_mgr, &s, device);
if (err < 0)
return err;
- err = uc_mgr_open_ctl(uc_mgr, &ctl, s);
+ err = uc_mgr_open_ctl(uc_mgr, &ctl, s, 1);
free(s);
if (err < 0)
return err;
struct list_head dev_list;
snd_ctl_t *ctl;
snd_ctl_card_info_t *ctl_info;
+ int slave;
};
struct ucm_dev_name {
void uc_mgr_free(snd_use_case_mgr_t *uc_mgr);
int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
- snd_ctl_t **ctl,
- const char *device);
+ struct ctl_list **ctl_list,
+ const char *device,
+ int slave);
-struct ctl_list *uc_mgr_get_one_ctl(snd_use_case_mgr_t *uc_mgr);
+struct ctl_list *uc_mgr_get_master_ctl(snd_use_case_mgr_t *uc_mgr);
+struct ctl_list *uc_mgr_get_ctl_by_name(snd_use_case_mgr_t *uc_mgr,
+ const char *name, int idx);
snd_ctl_t *uc_mgr_get_ctl(snd_use_case_mgr_t *uc_mgr);
void uc_mgr_free_ctl_list(snd_use_case_mgr_t *uc_mgr);
if (uc_mgr->conf_format < 3)
return NULL;
- ctl_list = uc_mgr_get_one_ctl(uc_mgr);
+ ctl_list = uc_mgr_get_master_ctl(uc_mgr);
if (ctl_list == NULL)
return strdup("");
snprintf(num, sizeof(num), "%i", snd_ctl_card_info_get_card(ctl_list->ctl_info));
{
struct ctl_list *ctl_list;
- ctl_list = uc_mgr_get_one_ctl(uc_mgr);
+ ctl_list = uc_mgr_get_master_ctl(uc_mgr);
if (ctl_list == NULL)
return NULL;
return strdup(snd_ctl_card_info_get_id(ctl_list->ctl_info));
{
struct ctl_list *ctl_list;
- ctl_list = uc_mgr_get_one_ctl(uc_mgr);
+ ctl_list = uc_mgr_get_master_ctl(uc_mgr);
if (ctl_list == NULL)
return NULL;
return strdup(snd_ctl_card_info_get_driver(ctl_list->ctl_info));
{
struct ctl_list *ctl_list;
- ctl_list = uc_mgr_get_one_ctl(uc_mgr);
+ ctl_list = uc_mgr_get_master_ctl(uc_mgr);
if (ctl_list == NULL)
return NULL;
return strdup(snd_ctl_card_info_get_name(ctl_list->ctl_info));
{
struct ctl_list *ctl_list;
- ctl_list = uc_mgr_get_one_ctl(uc_mgr);
+ ctl_list = uc_mgr_get_master_ctl(uc_mgr);
if (ctl_list == NULL)
return NULL;
return strdup(snd_ctl_card_info_get_longname(ctl_list->ctl_info));
{
struct ctl_list *ctl_list;
- ctl_list = uc_mgr_get_one_ctl(uc_mgr);
+ ctl_list = uc_mgr_get_master_ctl(uc_mgr);
if (ctl_list == NULL)
return NULL;
return strdup(snd_ctl_card_info_get_components(ctl_list->ctl_info));
}
+static char *rval_card_id_by_name(snd_use_case_mgr_t *uc_mgr, const char *id)
+{
+ struct ctl_list *ctl_list;
+ char *name, *index;
+ long idx = 0;
+
+ if (uc_mgr->conf_format < 3) {
+ uc_error("CardIdByName substitution is supported in v3+ syntax");
+ return NULL;
+ }
+
+ name = alloca(strlen(id) + 1);
+ strcpy(name, id);
+ index = strchr(name, '#');
+ if (index) {
+ *index = '\0';
+ if (safe_strtol(index + 1, &idx))
+ return NULL;
+ }
+ ctl_list = uc_mgr_get_ctl_by_name(uc_mgr, name, idx);
+ if (ctl_list == NULL)
+ return NULL;
+ return strdup(snd_ctl_card_info_get_id(ctl_list->ctl_info));
+}
+
static char *rval_env(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *id)
{
char *e;
MATCH_VARIABLE2(value, "${env:", rval_env);
MATCH_VARIABLE2(value, "${sys:", rval_sysfs);
MATCH_VARIABLE2(value, "${var:", rval_var);
+ MATCH_VARIABLE2(value, "${CardIdByName:", rval_card_id_by_name);
err = -EINVAL;
tmp = strchr(value, '}');
if (tmp) {
va_end(va);
}
-struct ctl_list *uc_mgr_get_one_ctl(snd_use_case_mgr_t *uc_mgr)
+struct ctl_list *uc_mgr_get_master_ctl(snd_use_case_mgr_t *uc_mgr)
{
struct list_head *pos;
- struct ctl_list *ctl_list = NULL;
+ struct ctl_list *ctl_list = NULL, *ctl_list2;
list_for_each(pos, &uc_mgr->ctl_list) {
+ ctl_list2 = list_entry(pos, struct ctl_list, list);
+ if (ctl_list2->slave)
+ continue;
if (ctl_list) {
uc_error("multiple control device names were found!");
return NULL;
}
- ctl_list = list_entry(pos, struct ctl_list, list);
+ ctl_list = ctl_list2;
}
return ctl_list;
}
+struct ctl_list *uc_mgr_get_ctl_by_name(snd_use_case_mgr_t *uc_mgr, const char *name, int idx)
+{
+ struct list_head *pos;
+ struct ctl_list *ctl_list = NULL;
+ const char *s;
+ char cname[32];
+ int idx2, card, err;
+
+ idx2 = idx;
+ list_for_each(pos, &uc_mgr->ctl_list) {
+ ctl_list = list_entry(pos, struct ctl_list, list);
+ s = snd_ctl_card_info_get_name(ctl_list->ctl_info);
+ if (s == NULL)
+ continue;
+ if (strcmp(s, name) == 0) {
+ if (idx2 == 0)
+ return ctl_list;
+ idx2--;
+ }
+ }
+
+ idx2 = idx;
+ card = -1;
+ if (snd_card_next(&card) < 0 || card < 0)
+ return NULL;
+
+ while (card >= 0) {
+ sprintf(cname, "hw:%d", card);
+ err = uc_mgr_open_ctl(uc_mgr, &ctl_list, cname, 1);
+ if (err < 0)
+ continue; /* really? */
+ s = snd_ctl_card_info_get_name(ctl_list->ctl_info);
+ if (s && strcmp(s, name) == 0) {
+ if (idx2 == 0)
+ return ctl_list;
+ idx2--;
+ }
+ if (snd_card_next(&card) < 0)
+ break;
+ }
+
+ return NULL;
+}
+
snd_ctl_t *uc_mgr_get_ctl(snd_use_case_mgr_t *uc_mgr)
{
struct ctl_list *ctl_list;
- ctl_list = uc_mgr_get_one_ctl(uc_mgr);
+ ctl_list = uc_mgr_get_master_ctl(uc_mgr);
if (ctl_list)
return ctl_list->ctl;
return NULL;
}
static int uc_mgr_ctl_add(snd_use_case_mgr_t *uc_mgr,
- struct ctl_list *ctl_list,
+ struct ctl_list **ctl_list,
snd_ctl_t *ctl, int card,
snd_ctl_card_info_t *info,
- const char *device)
+ const char *device,
+ int slave)
{
struct ctl_list *cl = NULL;
const char *id = snd_ctl_card_info_get_id(info);
if (id == NULL || id[0] == '\0')
return -ENOENT;
- if (!ctl_list) {
+ if (!(*ctl_list)) {
cl = malloc(sizeof(*cl));
if (cl == NULL)
return -ENOMEM;
return -ENOMEM;
}
snd_ctl_card_info_copy(cl->ctl_info, info);
- ctl_list = cl;
+ cl->slave = slave;
+ *ctl_list = cl;
+ } else {
+ if (!slave)
+ (*ctl_list)->slave = slave;
}
if (card >= 0) {
snprintf(dev, sizeof(dev), "hw:%d", card);
hit |= !!(device && (strcmp(dev, device) == 0));
- err = uc_mgr_ctl_add_dev(ctl_list, dev);
+ err = uc_mgr_ctl_add_dev(*ctl_list, dev);
if (err < 0)
goto __nomem;
}
snprintf(dev, sizeof(dev), "hw:%s", id);
hit |= !!(device && (strcmp(dev, device) == 0));
- err = uc_mgr_ctl_add_dev(ctl_list, dev);
+ err = uc_mgr_ctl_add_dev(*ctl_list, dev);
if (err < 0)
goto __nomem;
/* the UCM name not based on the card name / id */
if (!hit && device) {
- err = uc_mgr_ctl_add_dev(ctl_list, device);
+ err = uc_mgr_ctl_add_dev(*ctl_list, device);
if (err < 0)
goto __nomem;
}
- list_add_tail(&ctl_list->list, &uc_mgr->ctl_list);
+ list_add_tail(&(*ctl_list)->list, &uc_mgr->ctl_list);
return 0;
__nomem:
- if (ctl_list == cl)
+ if (*ctl_list == cl) {
uc_mgr_free_ctl(cl);
+ *ctl_list = NULL;
+ }
return -ENOMEM;
}
int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
- snd_ctl_t **ctl,
- const char *device)
+ struct ctl_list **ctll,
+ const char *device,
+ int slave)
{
struct list_head *pos1, *pos2;
+ snd_ctl_t *ctl;
struct ctl_list *ctl_list;
struct ctl_dev *ctl_dev;
snd_ctl_card_info_t *info;
list_for_each(pos2, &ctl_list->dev_list) {
ctl_dev = list_entry(pos2, struct ctl_dev, list);
if (strcmp(ctl_dev->device, device) == 0) {
- *ctl = ctl_list->ctl;
+ *ctll = ctl_list;
+ if (!slave)
+ ctl_list->slave = 0;
return 0;
}
}
}
- err = snd_ctl_open(ctl, device, 0);
+ err = snd_ctl_open(&ctl, device, 0);
if (err < 0)
return err;
id = NULL;
- err = snd_ctl_card_info(*ctl, info);
+ err = snd_ctl_card_info(ctl, info);
if (err == 0)
id = snd_ctl_card_info_get_id(info);
if (err < 0 || id == NULL || id[0] == '\0') {
uc_error("control hardware info (%s): %s", device, snd_strerror(err));
- snd_ctl_close(*ctl);
- *ctl = NULL;
+ snd_ctl_close(ctl);
return err;
}
ctl_list = list_entry(pos1, struct ctl_list, list);
if (strcmp(id, snd_ctl_card_info_get_id(ctl_list->ctl_info)) == 0) {
card = snd_card_get_index(id);
- err = uc_mgr_ctl_add(uc_mgr, ctl_list, *ctl, card, info, device);
+ err = uc_mgr_ctl_add(uc_mgr, &ctl_list, ctl, card, info, device, slave);
if (err < 0)
goto __nomem;
- snd_ctl_close(*ctl);
- *ctl = ctl_list->ctl;
+ snd_ctl_close(ctl);
+ *ctll = ctl_list;
return 0;
}
}
- err = uc_mgr_ctl_add(uc_mgr, NULL, *ctl, -1, info, device);
+ ctl_list = NULL;
+ err = uc_mgr_ctl_add(uc_mgr, &ctl_list, ctl, -1, info, device, slave);
if (err < 0)
goto __nomem;
+ *ctll = ctl_list;
return 0;
__nomem:
- snd_ctl_close(*ctl);
- *ctl = NULL;
+ snd_ctl_close(ctl);
return -ENOMEM;
}