mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	ucm: add support for multiple control devices, more aggresive caching
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
		
							parent
							
								
									be6deb927f
								
							
						
					
					
						commit
						32ff0ba7a3
					
				
					 4 changed files with 212 additions and 50 deletions
				
			
		| 
						 | 
					@ -138,37 +138,6 @@ int snd_use_case_free_list(const char *list[], int items)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
					 | 
				
			||||||
		    snd_ctl_t **ctl,
 | 
					 | 
				
			||||||
		    const char *ctl_dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* FIXME: add a list of ctl devices to uc_mgr structure and
 | 
					 | 
				
			||||||
           cache accesses for multiple opened ctl devices */
 | 
					 | 
				
			||||||
	if (uc_mgr->ctl_dev != NULL && strcmp(ctl_dev, uc_mgr->ctl_dev) == 0) {
 | 
					 | 
				
			||||||
		*ctl = uc_mgr->ctl;
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (uc_mgr->ctl_dev) {
 | 
					 | 
				
			||||||
		free(uc_mgr->ctl_dev);
 | 
					 | 
				
			||||||
		uc_mgr->ctl_dev = NULL;
 | 
					 | 
				
			||||||
		snd_ctl_close(uc_mgr->ctl);
 | 
					 | 
				
			||||||
		uc_mgr->ctl = NULL;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	err = snd_ctl_open(ctl, ctl_dev, 0);
 | 
					 | 
				
			||||||
	if (err < 0)
 | 
					 | 
				
			||||||
		return err;
 | 
					 | 
				
			||||||
	uc_mgr->ctl_dev = strdup(ctl_dev);
 | 
					 | 
				
			||||||
	if (uc_mgr->ctl_dev == NULL) {
 | 
					 | 
				
			||||||
		snd_ctl_close(*ctl);
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	uc_mgr->ctl = *ctl;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int read_tlv_file(unsigned int **res,
 | 
					static int read_tlv_file(unsigned int **res,
 | 
				
			||||||
			 const char *filepath)
 | 
								 const char *filepath)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -427,7 +396,7 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
					cdev = capture_ctl;
 | 
										cdev = capture_ctl;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (ctl == NULL) {
 | 
								if (ctl == NULL) {
 | 
				
			||||||
				err = open_ctl(uc_mgr, &ctl, cdev);
 | 
									err = uc_mgr_open_ctl(uc_mgr, &ctl, cdev);
 | 
				
			||||||
				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;
 | 
				
			||||||
| 
						 | 
					@ -932,6 +901,7 @@ int snd_use_case_mgr_open(snd_use_case_mgr_t **uc_mgr,
 | 
				
			||||||
	INIT_LIST_HEAD(&mgr->value_list);
 | 
						INIT_LIST_HEAD(&mgr->value_list);
 | 
				
			||||||
	INIT_LIST_HEAD(&mgr->active_modifiers);
 | 
						INIT_LIST_HEAD(&mgr->active_modifiers);
 | 
				
			||||||
	INIT_LIST_HEAD(&mgr->active_devices);
 | 
						INIT_LIST_HEAD(&mgr->active_devices);
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&mgr->ctl_list);
 | 
				
			||||||
	pthread_mutex_init(&mgr->mutex, NULL);
 | 
						pthread_mutex_init(&mgr->mutex, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mgr->card_name = strdup(card_name);
 | 
						mgr->card_name = strdup(card_name);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1412,22 +1412,27 @@ 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(const char *ctl_name, snd_ctl_card_info_t *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_t *handle;
 | 
						snd_ctl_t *handle;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = snd_ctl_open(&handle, ctl_name, 0);
 | 
						*_handle = NULL;
 | 
				
			||||||
	if (err < 0) {
 | 
					
 | 
				
			||||||
		uc_error("control open (%s): %s", ctl_name, snd_strerror(err));
 | 
						err = uc_mgr_open_ctl(mgr, &handle, ctl_name);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = snd_ctl_card_info(handle, info);
 | 
						err = snd_ctl_card_info(handle, info);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0) {
 | 
				
			||||||
		uc_error("control hardware info (%s): %s", ctl_name, snd_strerror(err));
 | 
							uc_error("control hardware info (%s): %s", ctl_name, snd_strerror(err));
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							*_handle = handle;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snd_ctl_close(handle);
 | 
					 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1436,6 +1441,7 @@ static int get_card_long_name(snd_use_case_mgr_t *mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *card_name = mgr->card_name;
 | 
						const char *card_name = mgr->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 *_name, *_long_name;
 | 
						const char *_name, *_long_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1451,7 +1457,7 @@ static int get_card_long_name(snd_use_case_mgr_t *mgr)
 | 
				
			||||||
		char name[32];
 | 
							char name[32];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sprintf(name, "hw:%d", card);
 | 
							sprintf(name, "hw:%d", card);
 | 
				
			||||||
		err = get_card_info(name, info);
 | 
							err = get_card_info(mgr, name, &ctl, info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (err == 0) {
 | 
							if (err == 0) {
 | 
				
			||||||
			_name = snd_ctl_card_info_get_name(info);
 | 
								_name = snd_ctl_card_info_get_name(info);
 | 
				
			||||||
| 
						 | 
					@ -1475,13 +1481,14 @@ static int get_card_long_name(snd_use_case_mgr_t *mgr)
 | 
				
			||||||
/* 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;
 | 
				
			||||||
	const char *_name, *_long_name;
 | 
						const char *_name, *_long_name;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snd_ctl_card_info_alloca(&info);
 | 
						snd_ctl_card_info_alloca(&info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = get_card_info(ctl_name, info);
 | 
						err = get_card_info(mgr, ctl_name, &ctl, info);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1490,6 +1497,7 @@ static int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snd_strlcpy(mgr->card_long_name, _long_name, sizeof(mgr->card_long_name));
 | 
						snd_strlcpy(mgr->card_long_name, _long_name, sizeof(mgr->card_long_name));
 | 
				
			||||||
	snd_strlcpy(mgr->conf_file_name, _name, sizeof(mgr->conf_file_name));
 | 
						snd_strlcpy(mgr->conf_file_name, _name, sizeof(mgr->conf_file_name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1572,6 +1580,7 @@ __parse:
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__error:
 | 
					__error:
 | 
				
			||||||
 | 
						uc_mgr_free_ctl_list(uc_mgr);
 | 
				
			||||||
	uc_mgr->conf_file_name[0] = '\0';
 | 
						uc_mgr->conf_file_name[0] = '\0';
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,6 +105,18 @@ struct dev_list {
 | 
				
			||||||
	struct list_head list;
 | 
						struct list_head list;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ctl_dev {
 | 
				
			||||||
 | 
						struct list_head list;
 | 
				
			||||||
 | 
						char *device;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ctl_list {
 | 
				
			||||||
 | 
						struct list_head list;
 | 
				
			||||||
 | 
						struct list_head dev_list;
 | 
				
			||||||
 | 
						char *ctl_id;
 | 
				
			||||||
 | 
						snd_ctl_t *ctl;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Describes a Use Case Modifier and it's enable and disable sequences.
 | 
					 * Describes a Use Case Modifier and it's enable and disable sequences.
 | 
				
			||||||
 * A use case verb can have N modifiers.
 | 
					 * A use case verb can have N modifiers.
 | 
				
			||||||
| 
						 | 
					@ -214,9 +226,8 @@ struct snd_use_case_mgr {
 | 
				
			||||||
	/* locking */
 | 
						/* locking */
 | 
				
			||||||
	pthread_mutex_t mutex;
 | 
						pthread_mutex_t mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* change to list of ctl handles */
 | 
						/* list of opened control devices */
 | 
				
			||||||
	snd_ctl_t *ctl;
 | 
						struct list_head ctl_list;
 | 
				
			||||||
	char *ctl_dev;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Components don't define cdev, the card device. When executing
 | 
						/* Components don't define cdev, the card device. When executing
 | 
				
			||||||
	 * a sequence of a component device, ucm manager enters component
 | 
						 * a sequence of a component device, ucm manager enters component
 | 
				
			||||||
| 
						 | 
					@ -247,6 +258,12 @@ void uc_mgr_free_transition_element(struct transition_sequence *seq);
 | 
				
			||||||
void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr);
 | 
					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,
 | 
				
			||||||
 | 
					                    snd_ctl_t **ctl,
 | 
				
			||||||
 | 
					                    const char *device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void uc_mgr_free_ctl_list(snd_use_case_mgr_t *uc_mgr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** The name of the environment variable containing the UCM directory */
 | 
					/** The name of the environment variable containing the UCM directory */
 | 
				
			||||||
#define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM"
 | 
					#define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										178
									
								
								src/ucm/utils.c
									
										
									
									
									
								
							
							
						
						
									
										178
									
								
								src/ucm/utils.c
									
										
									
									
									
								
							| 
						 | 
					@ -49,6 +49,177 @@ void uc_mgr_stdout(const char *fmt,...)
 | 
				
			||||||
	va_end(va);
 | 
						va_end(va);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void uc_mgr_free_ctl(struct ctl_list *ctl_list)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct list_head *pos, *npos;
 | 
				
			||||||
 | 
						struct ctl_dev *ctl_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_safe(pos, npos, &ctl_list->dev_list) {
 | 
				
			||||||
 | 
							ctl_dev = list_entry(pos, struct ctl_dev, list);
 | 
				
			||||||
 | 
							free(ctl_dev->device);
 | 
				
			||||||
 | 
							free(ctl_dev);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(ctl_list->ctl_id);
 | 
				
			||||||
 | 
						free(ctl_list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void uc_mgr_free_ctl_list(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct list_head *pos, *npos;
 | 
				
			||||||
 | 
						struct ctl_list *ctl_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_safe(pos, npos, &uc_mgr->ctl_list) {
 | 
				
			||||||
 | 
							ctl_list = list_entry(pos, struct ctl_list, list);
 | 
				
			||||||
 | 
							snd_ctl_close(ctl_list->ctl);
 | 
				
			||||||
 | 
							list_del(&ctl_list->list);
 | 
				
			||||||
 | 
							uc_mgr_free_ctl(ctl_list);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int uc_mgr_ctl_add_dev(struct ctl_list *ctl_list, const char *device)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct list_head *pos;
 | 
				
			||||||
 | 
						struct ctl_dev *ctl_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* skip duplicates */
 | 
				
			||||||
 | 
						list_for_each(pos, &ctl_list->dev_list) {
 | 
				
			||||||
 | 
							ctl_dev = list_entry(pos, struct ctl_dev, list);
 | 
				
			||||||
 | 
							if (strcmp(ctl_dev->device, device) == 0)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* allocate new device name */
 | 
				
			||||||
 | 
						ctl_dev = malloc(sizeof(*ctl_dev));
 | 
				
			||||||
 | 
						if (ctl_dev == NULL)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						ctl_dev->device = strdup(device);
 | 
				
			||||||
 | 
						if (ctl_dev->device == NULL) {
 | 
				
			||||||
 | 
							free(ctl_dev);
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						list_add_tail(&ctl_dev->list, &ctl_list->dev_list);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int uc_mgr_ctl_add(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
 | 
								  struct ctl_list *ctl_list,
 | 
				
			||||||
 | 
								  snd_ctl_t *ctl, int card, snd_ctl_card_info_t *info,
 | 
				
			||||||
 | 
								  const char *device)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ctl_list *cl = NULL;
 | 
				
			||||||
 | 
						const char *id = snd_ctl_card_info_get_id(info);
 | 
				
			||||||
 | 
						char dev[MAX_CARD_LONG_NAME];
 | 
				
			||||||
 | 
						int err, hit = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (id == NULL || id[0] == '\0')
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
						if (!ctl_list) {
 | 
				
			||||||
 | 
							cl = malloc(sizeof(*cl));
 | 
				
			||||||
 | 
							if (cl == NULL)
 | 
				
			||||||
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
							INIT_LIST_HEAD(&cl->dev_list);
 | 
				
			||||||
 | 
							cl->ctl = ctl;
 | 
				
			||||||
 | 
							cl->ctl_id = strdup(id);
 | 
				
			||||||
 | 
							if (cl->ctl_id == NULL) {
 | 
				
			||||||
 | 
								free(cl);
 | 
				
			||||||
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctl_list = cl;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
							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);
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								goto __nomem;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_add_tail(&ctl_list->list, &uc_mgr->ctl_list);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__nomem:
 | 
				
			||||||
 | 
						if (ctl_list == cl)
 | 
				
			||||||
 | 
							uc_mgr_free_ctl(cl);
 | 
				
			||||||
 | 
						return -ENOMEM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
 | 
							    snd_ctl_t **ctl,
 | 
				
			||||||
 | 
							    const char *device)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct list_head *pos1, *pos2;
 | 
				
			||||||
 | 
						struct ctl_list *ctl_list;
 | 
				
			||||||
 | 
						struct ctl_dev *ctl_dev;
 | 
				
			||||||
 | 
						snd_ctl_card_info_t *info;
 | 
				
			||||||
 | 
						const char *id;
 | 
				
			||||||
 | 
						int err, card;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snd_ctl_card_info_alloca(&info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* cache lookup */
 | 
				
			||||||
 | 
						list_for_each(pos1, &uc_mgr->ctl_list) {
 | 
				
			||||||
 | 
							ctl_list = list_entry(pos1, struct ctl_list, list);
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
									return 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = snd_ctl_open(ctl, device, 0);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						id = NULL;
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* insert to cache, if just name differs */
 | 
				
			||||||
 | 
						list_for_each(pos1, &uc_mgr->ctl_list) {
 | 
				
			||||||
 | 
							ctl_list = list_entry(pos1, struct ctl_list, list);
 | 
				
			||||||
 | 
							if (strcmp(id, ctl_list->ctl_id) == 0) {
 | 
				
			||||||
 | 
								card = snd_card_get_index(id);
 | 
				
			||||||
 | 
								err = uc_mgr_ctl_add(uc_mgr, ctl_list, *ctl, card, info, device);
 | 
				
			||||||
 | 
								if (err < 0)
 | 
				
			||||||
 | 
									goto __nomem;
 | 
				
			||||||
 | 
								snd_ctl_close(*ctl);
 | 
				
			||||||
 | 
								*ctl = ctl_list->ctl;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = uc_mgr_ctl_add(uc_mgr, NULL, *ctl, -1, info, device);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							goto __nomem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__nomem:
 | 
				
			||||||
 | 
						snd_ctl_close(*ctl);
 | 
				
			||||||
 | 
						*ctl = NULL;
 | 
				
			||||||
 | 
						return -ENOMEM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg)
 | 
					int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
| 
						 | 
					@ -241,17 +412,12 @@ void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
	uc_mgr->active_verb = NULL;
 | 
						uc_mgr->active_verb = NULL;
 | 
				
			||||||
	INIT_LIST_HEAD(&uc_mgr->active_devices);
 | 
						INIT_LIST_HEAD(&uc_mgr->active_devices);
 | 
				
			||||||
	INIT_LIST_HEAD(&uc_mgr->active_modifiers);
 | 
						INIT_LIST_HEAD(&uc_mgr->active_modifiers);
 | 
				
			||||||
	if (uc_mgr->ctl != NULL) {
 | 
					 | 
				
			||||||
		snd_ctl_close(uc_mgr->ctl);
 | 
					 | 
				
			||||||
		uc_mgr->ctl = NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	free(uc_mgr->ctl_dev);
 | 
					 | 
				
			||||||
	uc_mgr->ctl_dev = NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void uc_mgr_free(snd_use_case_mgr_t *uc_mgr)
 | 
					void uc_mgr_free(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uc_mgr_free_verb(uc_mgr);
 | 
						uc_mgr_free_verb(uc_mgr);
 | 
				
			||||||
 | 
						uc_mgr_free_ctl_list(uc_mgr);
 | 
				
			||||||
	free(uc_mgr->card_name);
 | 
						free(uc_mgr->card_name);
 | 
				
			||||||
	free(uc_mgr);
 | 
						free(uc_mgr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue