mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	ucm: implement CardIdByName substitution
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>
			
			
This commit is contained in:
		
							parent
							
								
									f60e0d5fdc
								
							
						
					
					
						commit
						eee879d381
					
				
					 6 changed files with 135 additions and 56 deletions
				
			
		| 
						 | 
					@ -333,6 +333,7 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
	struct sequence_element *s;
 | 
						struct sequence_element *s;
 | 
				
			||||||
	char *cdev = NULL;
 | 
						char *cdev = NULL;
 | 
				
			||||||
	snd_ctl_t *ctl = NULL;
 | 
						snd_ctl_t *ctl = NULL;
 | 
				
			||||||
 | 
						struct ctl_list *ctl_list;
 | 
				
			||||||
	int err = 0;
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each(pos, seq) {
 | 
						list_for_each(pos, seq) {
 | 
				
			||||||
| 
						 | 
					@ -400,11 +401,12 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (ctl == NULL) {
 | 
								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) {
 | 
									if (err < 0) {
 | 
				
			||||||
					uc_error("unable to open ctl device '%s'", cdev);
 | 
										uc_error("unable to open ctl device '%s'", cdev);
 | 
				
			||||||
					goto __fail;
 | 
										goto __fail;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									ctl = ctl_list->ctl;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			err = execute_cset(ctl, s->data.cset, s->type);
 | 
								err = execute_cset(ctl, s->data.cset, s->type);
 | 
				
			||||||
			if (err < 0) {
 | 
								if (err < 0) {
 | 
				
			||||||
| 
						 | 
					@ -516,7 +518,7 @@ static int add_auto_values(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
	char buf[40];
 | 
						char buf[40];
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctl_list = uc_mgr_get_one_ctl(uc_mgr);
 | 
						ctl_list = uc_mgr_get_master_ctl(uc_mgr);
 | 
				
			||||||
	if (ctl_list) {
 | 
						if (ctl_list) {
 | 
				
			||||||
		id = snd_ctl_card_info_get_id(ctl_list->ctl_info);
 | 
							id = snd_ctl_card_info_get_id(ctl_list->ctl_info);
 | 
				
			||||||
		snprintf(buf, sizeof(buf), "hw:%s", id);
 | 
							snprintf(buf, sizeof(buf), "hw:%s", id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1901,25 +1901,16 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
 | 
				
			||||||
/* get the card info */
 | 
					/* get the card info */
 | 
				
			||||||
static int get_card_info(snd_use_case_mgr_t *mgr,
 | 
					static int get_card_info(snd_use_case_mgr_t *mgr,
 | 
				
			||||||
			 const char *ctl_name,
 | 
								 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;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*_handle = NULL;
 | 
						err = uc_mgr_open_ctl(mgr, &ctl_list, ctl_name, 0);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = uc_mgr_open_ctl(mgr, &handle, ctl_name);
 | 
					 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = snd_ctl_card_info(handle, info);
 | 
						*info = ctl_list->ctl_info;
 | 
				
			||||||
	if (err < 0) {
 | 
					 | 
				
			||||||
		uc_error("control hardware info (%s): %s", ctl_name, snd_strerror(err));
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		*_handle = handle;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1927,7 +1918,6 @@ static int get_card_info(snd_use_case_mgr_t *mgr,
 | 
				
			||||||
static int get_by_card_name(snd_use_case_mgr_t *mgr, const char *card_name)
 | 
					static int get_by_card_name(snd_use_case_mgr_t *mgr, const char *card_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int card, err;
 | 
						int card, err;
 | 
				
			||||||
	snd_ctl_t *ctl;
 | 
					 | 
				
			||||||
	snd_ctl_card_info_t *info;
 | 
						snd_ctl_card_info_t *info;
 | 
				
			||||||
	const char *_driver, *_name, *_long_name;
 | 
						const char *_driver, *_name, *_long_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1942,11 +1932,11 @@ static int get_by_card_name(snd_use_case_mgr_t *mgr, const char *card_name)
 | 
				
			||||||
	while (card >= 0) {
 | 
						while (card >= 0) {
 | 
				
			||||||
		char name[32];
 | 
							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);
 | 
							uc_mgr_free_ctl_list(mgr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sprintf(name, "hw:%d", card);
 | 
							sprintf(name, "hw:%d", card);
 | 
				
			||||||
		err = get_card_info(mgr, name, &ctl, info);
 | 
							err = get_card_info(mgr, name, &info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (err == 0) {
 | 
							if (err == 0) {
 | 
				
			||||||
			_driver = snd_ctl_card_info_get_driver(info);
 | 
								_driver = snd_ctl_card_info_get_driver(info);
 | 
				
			||||||
| 
						 | 
					@ -1972,13 +1962,12 @@ static int get_by_card_name(snd_use_case_mgr_t *mgr, const char *card_name)
 | 
				
			||||||
/* set the driver name and long name by the card ctl name */
 | 
					/* 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)
 | 
					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;
 | 
						snd_ctl_card_info_t *info;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snd_ctl_card_info_alloca(&info);
 | 
						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)
 | 
						if (err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -228,7 +228,7 @@ static int if_eval_control_exists(snd_use_case_mgr_t *uc_mgr, snd_config_t *eval
 | 
				
			||||||
		err = uc_mgr_get_substituted_value(uc_mgr, &s, device);
 | 
							err = uc_mgr_get_substituted_value(uc_mgr, &s, device);
 | 
				
			||||||
		if (err < 0)
 | 
							if (err < 0)
 | 
				
			||||||
			return err;
 | 
								return err;
 | 
				
			||||||
		err = uc_mgr_open_ctl(uc_mgr, &ctl, s);
 | 
							err = uc_mgr_open_ctl(uc_mgr, &ctl, s, 1);
 | 
				
			||||||
		free(s);
 | 
							free(s);
 | 
				
			||||||
		if (err < 0)
 | 
							if (err < 0)
 | 
				
			||||||
			return err;
 | 
								return err;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,6 +115,7 @@ struct ctl_list {
 | 
				
			||||||
	struct list_head dev_list;
 | 
						struct list_head dev_list;
 | 
				
			||||||
	snd_ctl_t *ctl;
 | 
						snd_ctl_t *ctl;
 | 
				
			||||||
	snd_ctl_card_info_t *ctl_info;
 | 
						snd_ctl_card_info_t *ctl_info;
 | 
				
			||||||
 | 
						int slave;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ucm_dev_name {
 | 
					struct ucm_dev_name {
 | 
				
			||||||
| 
						 | 
					@ -283,10 +284,13 @@ void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr);
 | 
				
			||||||
void uc_mgr_free(snd_use_case_mgr_t *uc_mgr);
 | 
					void uc_mgr_free(snd_use_case_mgr_t *uc_mgr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
					int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
                    snd_ctl_t **ctl,
 | 
							    struct ctl_list **ctl_list,
 | 
				
			||||||
                    const char *device);
 | 
							    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);
 | 
					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);
 | 
					void uc_mgr_free_ctl_list(snd_use_case_mgr_t *uc_mgr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,7 @@ static char *rval_card_number(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (uc_mgr->conf_format < 3)
 | 
						if (uc_mgr->conf_format < 3)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	ctl_list = uc_mgr_get_one_ctl(uc_mgr);
 | 
						ctl_list = uc_mgr_get_master_ctl(uc_mgr);
 | 
				
			||||||
	if (ctl_list == NULL)
 | 
						if (ctl_list == NULL)
 | 
				
			||||||
		return strdup("");
 | 
							return strdup("");
 | 
				
			||||||
	snprintf(num, sizeof(num), "%i", snd_ctl_card_info_get_card(ctl_list->ctl_info));
 | 
						snprintf(num, sizeof(num), "%i", snd_ctl_card_info_get_card(ctl_list->ctl_info));
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ static char *rval_card_id(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ctl_list *ctl_list;
 | 
						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)
 | 
						if (ctl_list == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	return strdup(snd_ctl_card_info_get_id(ctl_list->ctl_info));
 | 
						return strdup(snd_ctl_card_info_get_id(ctl_list->ctl_info));
 | 
				
			||||||
| 
						 | 
					@ -94,7 +94,7 @@ static char *rval_card_driver(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ctl_list *ctl_list;
 | 
						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)
 | 
						if (ctl_list == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	return strdup(snd_ctl_card_info_get_driver(ctl_list->ctl_info));
 | 
						return strdup(snd_ctl_card_info_get_driver(ctl_list->ctl_info));
 | 
				
			||||||
| 
						 | 
					@ -104,7 +104,7 @@ static char *rval_card_name(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ctl_list *ctl_list;
 | 
						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)
 | 
						if (ctl_list == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	return strdup(snd_ctl_card_info_get_name(ctl_list->ctl_info));
 | 
						return strdup(snd_ctl_card_info_get_name(ctl_list->ctl_info));
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,7 @@ static char *rval_card_longname(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ctl_list *ctl_list;
 | 
						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)
 | 
						if (ctl_list == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	return strdup(snd_ctl_card_info_get_longname(ctl_list->ctl_info));
 | 
						return strdup(snd_ctl_card_info_get_longname(ctl_list->ctl_info));
 | 
				
			||||||
| 
						 | 
					@ -124,12 +124,37 @@ static char *rval_card_components(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ctl_list *ctl_list;
 | 
						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)
 | 
						if (ctl_list == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	return strdup(snd_ctl_card_info_get_components(ctl_list->ctl_info));
 | 
						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)
 | 
					static char *rval_env(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *e;
 | 
						char *e;
 | 
				
			||||||
| 
						 | 
					@ -265,6 +290,7 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
			MATCH_VARIABLE2(value, "${env:", rval_env);
 | 
								MATCH_VARIABLE2(value, "${env:", rval_env);
 | 
				
			||||||
			MATCH_VARIABLE2(value, "${sys:", rval_sysfs);
 | 
								MATCH_VARIABLE2(value, "${sys:", rval_sysfs);
 | 
				
			||||||
			MATCH_VARIABLE2(value, "${var:", rval_var);
 | 
								MATCH_VARIABLE2(value, "${var:", rval_var);
 | 
				
			||||||
 | 
								MATCH_VARIABLE2(value, "${CardIdByName:", rval_card_id_by_name);
 | 
				
			||||||
			err = -EINVAL;
 | 
								err = -EINVAL;
 | 
				
			||||||
			tmp = strchr(value, '}');
 | 
								tmp = strchr(value, '}');
 | 
				
			||||||
			if (tmp) {
 | 
								if (tmp) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										110
									
								
								src/ucm/utils.c
									
										
									
									
									
								
							
							
						
						
									
										110
									
								
								src/ucm/utils.c
									
										
									
									
									
								
							| 
						 | 
					@ -49,26 +49,73 @@ void uc_mgr_stdout(const char *fmt,...)
 | 
				
			||||||
	va_end(va);
 | 
						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 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) {
 | 
						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) {
 | 
							if (ctl_list) {
 | 
				
			||||||
			uc_error("multiple control device names were found!");
 | 
								uc_error("multiple control device names were found!");
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctl_list = list_entry(pos, struct ctl_list, list);
 | 
							ctl_list = ctl_list2;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ctl_list;
 | 
						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)
 | 
					snd_ctl_t *uc_mgr_get_ctl(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ctl_list *ctl_list;
 | 
						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)
 | 
						if (ctl_list)
 | 
				
			||||||
		return ctl_list->ctl;
 | 
							return ctl_list->ctl;
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
| 
						 | 
					@ -127,10 +174,11 @@ static int uc_mgr_ctl_add_dev(struct ctl_list *ctl_list, const char *device)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int uc_mgr_ctl_add(snd_use_case_mgr_t *uc_mgr,
 | 
					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_t *ctl, int card,
 | 
				
			||||||
			  snd_ctl_card_info_t *info,
 | 
								  snd_ctl_card_info_t *info,
 | 
				
			||||||
			  const char *device)
 | 
								  const char *device,
 | 
				
			||||||
 | 
								  int slave)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ctl_list *cl = NULL;
 | 
						struct ctl_list *cl = NULL;
 | 
				
			||||||
	const char *id = snd_ctl_card_info_get_id(info);
 | 
						const char *id = snd_ctl_card_info_get_id(info);
 | 
				
			||||||
| 
						 | 
					@ -139,7 +187,7 @@ static int uc_mgr_ctl_add(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (id == NULL || id[0] == '\0')
 | 
						if (id == NULL || id[0] == '\0')
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
	if (!ctl_list) {
 | 
						if (!(*ctl_list)) {
 | 
				
			||||||
		cl = malloc(sizeof(*cl));
 | 
							cl = malloc(sizeof(*cl));
 | 
				
			||||||
		if (cl == NULL)
 | 
							if (cl == NULL)
 | 
				
			||||||
			return -ENOMEM;
 | 
								return -ENOMEM;
 | 
				
			||||||
| 
						 | 
					@ -150,41 +198,49 @@ static int uc_mgr_ctl_add(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
			return -ENOMEM;
 | 
								return -ENOMEM;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		snd_ctl_card_info_copy(cl->ctl_info, info);
 | 
							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) {
 | 
						if (card >= 0) {
 | 
				
			||||||
		snprintf(dev, sizeof(dev), "hw:%d", card);
 | 
							snprintf(dev, sizeof(dev), "hw:%d", card);
 | 
				
			||||||
		hit |= !!(device && (strcmp(dev, device) == 0));
 | 
							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)
 | 
							if (err < 0)
 | 
				
			||||||
			goto __nomem;
 | 
								goto __nomem;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	snprintf(dev, sizeof(dev), "hw:%s", id);
 | 
						snprintf(dev, sizeof(dev), "hw:%s", id);
 | 
				
			||||||
	hit |= !!(device && (strcmp(dev, device) == 0));
 | 
						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)
 | 
						if (err < 0)
 | 
				
			||||||
		goto __nomem;
 | 
							goto __nomem;
 | 
				
			||||||
	/* the UCM name not based on the card name / id */
 | 
						/* the UCM name not based on the card name / id */
 | 
				
			||||||
	if (!hit && device) {
 | 
						if (!hit && device) {
 | 
				
			||||||
		err = uc_mgr_ctl_add_dev(ctl_list, device);
 | 
							err = uc_mgr_ctl_add_dev(*ctl_list, device);
 | 
				
			||||||
		if (err < 0)
 | 
							if (err < 0)
 | 
				
			||||||
			goto __nomem;
 | 
								goto __nomem;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_add_tail(&ctl_list->list, &uc_mgr->ctl_list);
 | 
						list_add_tail(&(*ctl_list)->list, &uc_mgr->ctl_list);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__nomem:
 | 
					__nomem:
 | 
				
			||||||
	if (ctl_list == cl)
 | 
						if (*ctl_list == cl) {
 | 
				
			||||||
		uc_mgr_free_ctl(cl);
 | 
							uc_mgr_free_ctl(cl);
 | 
				
			||||||
 | 
							*ctl_list = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return -ENOMEM;
 | 
						return -ENOMEM;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
					int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
		    snd_ctl_t **ctl,
 | 
							    struct ctl_list **ctll,
 | 
				
			||||||
		    const char *device)
 | 
							    const char *device,
 | 
				
			||||||
 | 
							    int slave)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct list_head *pos1, *pos2;
 | 
						struct list_head *pos1, *pos2;
 | 
				
			||||||
 | 
						snd_ctl_t *ctl;
 | 
				
			||||||
	struct ctl_list *ctl_list;
 | 
						struct ctl_list *ctl_list;
 | 
				
			||||||
	struct ctl_dev *ctl_dev;
 | 
						struct ctl_dev *ctl_dev;
 | 
				
			||||||
	snd_ctl_card_info_t *info;
 | 
						snd_ctl_card_info_t *info;
 | 
				
			||||||
| 
						 | 
					@ -199,24 +255,25 @@ int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
		list_for_each(pos2, &ctl_list->dev_list) {
 | 
							list_for_each(pos2, &ctl_list->dev_list) {
 | 
				
			||||||
			ctl_dev = list_entry(pos2, struct ctl_dev, list);
 | 
								ctl_dev = list_entry(pos2, struct ctl_dev, list);
 | 
				
			||||||
			if (strcmp(ctl_dev->device, device) == 0) {
 | 
								if (strcmp(ctl_dev->device, device) == 0) {
 | 
				
			||||||
				*ctl = ctl_list->ctl;
 | 
									*ctll = ctl_list;
 | 
				
			||||||
 | 
									if (!slave)
 | 
				
			||||||
 | 
										ctl_list->slave = 0;
 | 
				
			||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = snd_ctl_open(ctl, device, 0);
 | 
						err = snd_ctl_open(&ctl, device, 0);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	id = NULL;
 | 
						id = NULL;
 | 
				
			||||||
	err = snd_ctl_card_info(*ctl, info);
 | 
						err = snd_ctl_card_info(ctl, info);
 | 
				
			||||||
	if (err == 0)
 | 
						if (err == 0)
 | 
				
			||||||
		id = snd_ctl_card_info_get_id(info);
 | 
							id = snd_ctl_card_info_get_id(info);
 | 
				
			||||||
	if (err < 0 || id == NULL || id[0] == '\0') {
 | 
						if (err < 0 || id == NULL || id[0] == '\0') {
 | 
				
			||||||
		uc_error("control hardware info (%s): %s", device, snd_strerror(err));
 | 
							uc_error("control hardware info (%s): %s", device, snd_strerror(err));
 | 
				
			||||||
		snd_ctl_close(*ctl);
 | 
							snd_ctl_close(ctl);
 | 
				
			||||||
		*ctl = NULL;
 | 
					 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -225,24 +282,25 @@ int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
		ctl_list = list_entry(pos1, struct ctl_list, list);
 | 
							ctl_list = list_entry(pos1, struct ctl_list, list);
 | 
				
			||||||
		if (strcmp(id, snd_ctl_card_info_get_id(ctl_list->ctl_info)) == 0) {
 | 
							if (strcmp(id, snd_ctl_card_info_get_id(ctl_list->ctl_info)) == 0) {
 | 
				
			||||||
			card = snd_card_get_index(id);
 | 
								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)
 | 
								if (err < 0)
 | 
				
			||||||
				goto __nomem;
 | 
									goto __nomem;
 | 
				
			||||||
			snd_ctl_close(*ctl);
 | 
								snd_ctl_close(ctl);
 | 
				
			||||||
			*ctl = ctl_list->ctl;
 | 
								*ctll = ctl_list;
 | 
				
			||||||
			return 0;
 | 
								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)
 | 
						if (err < 0)
 | 
				
			||||||
		goto __nomem;
 | 
							goto __nomem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ctll = ctl_list;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__nomem:
 | 
					__nomem:
 | 
				
			||||||
	snd_ctl_close(*ctl);
 | 
						snd_ctl_close(ctl);
 | 
				
			||||||
	*ctl = NULL;
 | 
					 | 
				
			||||||
	return -ENOMEM;
 | 
						return -ENOMEM;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue