mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-02-05 04:06:34 -05:00
ucm: strip device index when the device type is present only one time
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
48c477569d
commit
e83fd7806f
1 changed files with 128 additions and 33 deletions
161
src/ucm/parser.c
161
src/ucm/parser.c
|
|
@ -1891,6 +1891,52 @@ static int is_device_name_used(struct use_case_verb *verb, const char *name, str
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update all references to a device name in modifiers and other devices.
|
||||||
|
* This helper function is used when renaming devices to ensure all
|
||||||
|
* dev_list references are updated accordingly.
|
||||||
|
*/
|
||||||
|
static int verb_update_device_references(struct use_case_verb *verb,
|
||||||
|
const char *old_name,
|
||||||
|
const char *new_name)
|
||||||
|
{
|
||||||
|
struct list_head *pos, *pos2;
|
||||||
|
struct use_case_device *device;
|
||||||
|
struct use_case_modifier *modifier;
|
||||||
|
struct dev_list_node *dlist;
|
||||||
|
char *name_copy;
|
||||||
|
|
||||||
|
list_for_each(pos, &verb->modifier_list) {
|
||||||
|
modifier = list_entry(pos, struct use_case_modifier, list);
|
||||||
|
list_for_each(pos2, &modifier->dev_list.list) {
|
||||||
|
dlist = list_entry(pos2, struct dev_list_node, list);
|
||||||
|
if (strcmp(dlist->name, old_name) == 0) {
|
||||||
|
name_copy = strdup(new_name);
|
||||||
|
if (name_copy == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
free(dlist->name);
|
||||||
|
dlist->name = name_copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each(pos, &verb->device_list) {
|
||||||
|
device = list_entry(pos, struct use_case_device, list);
|
||||||
|
list_for_each(pos2, &device->dev_list.list) {
|
||||||
|
dlist = list_entry(pos2, struct dev_list_node, list);
|
||||||
|
if (strcmp(dlist->name, old_name) == 0) {
|
||||||
|
name_copy = strdup(new_name);
|
||||||
|
if (name_copy == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
free(dlist->name);
|
||||||
|
dlist->name = name_copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Normalize device names according to use-case.h specification.
|
* Normalize device names according to use-case.h specification.
|
||||||
* Device names like "HDMI 1" or "Line 1" should be normalized to "HDMI1" and "Line1".
|
* Device names like "HDMI 1" or "Line 1" should be normalized to "HDMI1" and "Line1".
|
||||||
|
|
@ -1900,10 +1946,8 @@ static int is_device_name_used(struct use_case_verb *verb, const char *name, str
|
||||||
*/
|
*/
|
||||||
static int verb_normalize_device_names(snd_use_case_mgr_t *uc_mgr, struct use_case_verb *verb)
|
static int verb_normalize_device_names(snd_use_case_mgr_t *uc_mgr, struct use_case_verb *verb)
|
||||||
{
|
{
|
||||||
struct list_head *pos, *pos2, *pos3;
|
struct list_head *pos;
|
||||||
struct use_case_device *device, *device2;
|
struct use_case_device *device;
|
||||||
struct use_case_modifier *modifier;
|
|
||||||
struct dev_list_node *dlist;
|
|
||||||
char *orig_name, *norm_name, *colon;
|
char *orig_name, *norm_name, *colon;
|
||||||
char temp[80];
|
char temp[80];
|
||||||
int err, index;
|
int err, index;
|
||||||
|
|
@ -1963,35 +2007,10 @@ __no_colon:
|
||||||
goto __error;
|
goto __error;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each(pos2, &verb->modifier_list) {
|
/* Update all references to the old device name */
|
||||||
modifier = list_entry(pos2, struct use_case_modifier, list);
|
err = verb_update_device_references(verb, orig_name, device->name);
|
||||||
list_for_each(pos3, &modifier->dev_list.list) {
|
if (err < 0)
|
||||||
dlist = list_entry(pos3, struct dev_list_node, list);
|
goto __error;
|
||||||
if (strcmp(dlist->name, orig_name) == 0) {
|
|
||||||
free(dlist->name);
|
|
||||||
dlist->name = strdup(device->name);
|
|
||||||
if (dlist->name == NULL) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto __error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each(pos2, &verb->device_list) {
|
|
||||||
device2 = list_entry(pos2, struct use_case_device, list);
|
|
||||||
list_for_each(pos3, &device2->dev_list.list) {
|
|
||||||
dlist = list_entry(pos3, struct dev_list_node, list);
|
|
||||||
if (strcmp(dlist->name, orig_name) == 0) {
|
|
||||||
free(dlist->name);
|
|
||||||
dlist->name = strdup(device->name);
|
|
||||||
if (dlist->name == NULL) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto __error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(orig_name);
|
free(orig_name);
|
||||||
free(norm_name);
|
free(norm_name);
|
||||||
|
|
@ -2005,6 +2024,75 @@ __error:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip index from single device names.
|
||||||
|
* According to use-case.h specification, if there is only one device
|
||||||
|
* with a given base name (e.g., only "HDMI1" and no "HDMI2"), the index
|
||||||
|
* should be stripped to produce the final name (e.g., "HDMI").
|
||||||
|
*/
|
||||||
|
static int verb_strip_single_device_index(struct use_case_verb *verb)
|
||||||
|
{
|
||||||
|
struct list_head *pos, *pos2;
|
||||||
|
struct use_case_device *device, *device2;
|
||||||
|
char *base_name, *test_base;
|
||||||
|
char *orig_name;
|
||||||
|
int count, index, test_index, err;
|
||||||
|
|
||||||
|
list_for_each(pos, &verb->device_list) {
|
||||||
|
device = list_entry(pos, struct use_case_device, list);
|
||||||
|
|
||||||
|
base_name = strdup(device->name);
|
||||||
|
if (base_name == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
err = parse_device_index(&base_name, &index);
|
||||||
|
if (err < 0) {
|
||||||
|
free(base_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index <= 0) {
|
||||||
|
free(base_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count how many devices have the same base name */
|
||||||
|
count = 0;
|
||||||
|
list_for_each(pos2, &verb->device_list) {
|
||||||
|
device2 = list_entry(pos2, struct use_case_device, list);
|
||||||
|
test_base = strdup(device2->name);
|
||||||
|
if (test_base == NULL) {
|
||||||
|
free(base_name);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = parse_device_index(&test_base, &test_index);
|
||||||
|
if (err >= 0 && strcmp(test_base, base_name) == 0)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
free(test_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 1) {
|
||||||
|
orig_name = device->name;
|
||||||
|
device->name = base_name;
|
||||||
|
|
||||||
|
err = verb_update_device_references(verb, orig_name, device->name);
|
||||||
|
if (err < 0) {
|
||||||
|
device->name = orig_name;
|
||||||
|
free(base_name);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(orig_name);
|
||||||
|
} else {
|
||||||
|
free(base_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int verb_device_management(snd_use_case_mgr_t *uc_mgr, struct use_case_verb *verb)
|
static int verb_device_management(snd_use_case_mgr_t *uc_mgr, struct use_case_verb *verb)
|
||||||
{
|
{
|
||||||
struct list_head *pos;
|
struct list_head *pos;
|
||||||
|
|
@ -2040,6 +2128,13 @@ static int verb_device_management(snd_use_case_mgr_t *uc_mgr, struct use_case_ve
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
/* strip index from single device names */
|
||||||
|
if (uc_mgr->conf_format >= 8) {
|
||||||
|
err = verb_strip_single_device_index(verb);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* handle conflicting/supported lists */
|
/* handle conflicting/supported lists */
|
||||||
return verb_dev_list_check(verb);
|
return verb_dev_list_check(verb);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue