mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-10-29 05:40:25 -04:00 
			
		
		
		
	ucm: added implementation for other ucm parts, only card name list is missing
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
		
							parent
							
								
									404cd090b2
								
							
						
					
					
						commit
						6c6dc230bc
					
				
					 2 changed files with 220 additions and 12 deletions
				
			
		
							
								
								
									
										228
									
								
								src/ucm/main.c
									
										
									
									
									
								
							
							
						
						
									
										228
									
								
								src/ucm/main.c
									
										
									
									
									
								
							|  | @ -313,6 +313,21 @@ static inline struct use_case_verb *find_verb(snd_use_case_mgr_t *uc_mgr, | |||
| 		    verb_name); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Find device | ||||
|  * \param verb Use case verb | ||||
|  * \param device_name device to find | ||||
|  * \return structure on success, otherwise a NULL (not found) | ||||
|  */ | ||||
| static inline struct use_case_device * | ||||
|         find_device(struct use_case_verb *verb, | ||||
|                       const char *device_name) | ||||
| { | ||||
| 	return find(&verb->device_list, | ||||
| 		    struct use_case_device, list, name, | ||||
| 		    device_name); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Find modifier | ||||
|  * \param verb Use case verb | ||||
|  | @ -488,20 +503,16 @@ int snd_use_case_mgr_close(snd_use_case_mgr_t *uc_mgr) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Reset sound card controls to default values. | ||||
|  * \param uc_mgr Use case manager | ||||
|  * \return zero on success, otherwise a negative error code | ||||
| /*
 | ||||
|  * Tear down current use case verb, device and modifier. | ||||
|  */ | ||||
| int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr) | ||||
| static int dismantle_use_case(snd_use_case_mgr_t *uc_mgr) | ||||
| { | ||||
| 	struct list_head *pos, *npos; | ||||
| 	struct use_case_modifier *modifier; | ||||
| 	struct use_case_device *device; | ||||
| 	int err; | ||||
| 
 | ||||
| 	pthread_mutex_lock(&uc_mgr->mutex); | ||||
| 
 | ||||
| 	list_for_each_safe(pos, npos, &uc_mgr->active_modifiers) { | ||||
| 		modifier = list_entry(pos, struct use_case_modifier, | ||||
| 				      active_list); | ||||
|  | @ -529,6 +540,23 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr) | |||
| 
 | ||||
| 	err = execute_sequence(uc_mgr, &uc_mgr->default_list); | ||||
| 	 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Reset sound card controls to default values. | ||||
|  * \param uc_mgr Use case manager | ||||
|  * \return zero on success, otherwise a negative error code | ||||
|  */ | ||||
| int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr) | ||||
| { | ||||
|         int err; | ||||
| 
 | ||||
| 	pthread_mutex_lock(&uc_mgr->mutex); | ||||
| 	err = execute_sequence(uc_mgr, &uc_mgr->default_list); | ||||
| 	INIT_LIST_HEAD(&uc_mgr->active_modifiers); | ||||
| 	INIT_LIST_HEAD(&uc_mgr->active_devices); | ||||
| 	uc_mgr->active_verb = NULL; | ||||
| 	pthread_mutex_unlock(&uc_mgr->mutex); | ||||
| 	return err; | ||||
| } | ||||
|  | @ -950,6 +978,190 @@ long snd_use_case_geti(snd_use_case_mgr_t *uc_mgr, | |||
|         return err; | ||||
| } | ||||
| 
 | ||||
| static int handle_transition_verb(snd_use_case_mgr_t *uc_mgr, | ||||
|                                   struct use_case_verb *new_verb) | ||||
| { | ||||
|         struct list_head *pos; | ||||
|         struct transition_sequence *trans; | ||||
|         int err; | ||||
| 
 | ||||
|         list_for_each(pos, &uc_mgr->active_verb->transition_list) { | ||||
|                 trans = list_entry(pos, struct transition_sequence, list); | ||||
|                 if (strcmp(trans->name, new_verb->name) == 0) { | ||||
|                         err = execute_sequence(uc_mgr, &trans->transition_list); | ||||
|                         if (err >= 0) | ||||
|                                 return 1; | ||||
|                         return err; | ||||
|                 } | ||||
|         } | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| static int set_verb_user(snd_use_case_mgr_t *uc_mgr, | ||||
|                          const char *verb_name) | ||||
| { | ||||
|         struct use_case_verb *verb; | ||||
|         int err; | ||||
| 
 | ||||
|         if (uc_mgr->active_verb && | ||||
|             strcmp(uc_mgr->active_verb->name, verb_name) == 0) | ||||
|                 return 0; | ||||
|         if (strcmp(verb_name, SND_USE_CASE_VERB_INACTIVE) != 0) { | ||||
|                 verb = find_verb(uc_mgr, verb_name); | ||||
|                 if (verb == NULL) | ||||
|                         return -ENOENT; | ||||
|         } else { | ||||
|                 verb = NULL; | ||||
|         } | ||||
|         if (uc_mgr->active_verb) { | ||||
|                 err = handle_transition_verb(uc_mgr, verb); | ||||
|                 if (err == 0) { | ||||
|                         err = dismantle_use_case(uc_mgr); | ||||
|                         if (err < 0) | ||||
|                                 return err; | ||||
|                 } else if (err == 1) { | ||||
|                         uc_mgr->active_verb = verb; | ||||
|                         verb = NULL; | ||||
|                 } else { | ||||
|                         verb = NULL; /* show error */ | ||||
|                 } | ||||
|         } | ||||
|         if (verb) { | ||||
|                 err = set_verb(uc_mgr, verb, 1); | ||||
|                 if (err < 0) | ||||
|                         uc_error("error: failed to initialize new use case: %s", | ||||
|                                  verb_name); | ||||
|         } | ||||
|         return err; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int set_device_user(snd_use_case_mgr_t *uc_mgr, | ||||
|                            const char *device_name, | ||||
|                            int enable) | ||||
| { | ||||
|         struct use_case_device *device; | ||||
| 
 | ||||
|         if (uc_mgr->active_verb == NULL) | ||||
|                 return -ENOENT; | ||||
|         device = find_device(uc_mgr->active_verb, device_name); | ||||
|         if (device == NULL) | ||||
|                 return -ENOENT; | ||||
|         return set_device(uc_mgr, device, enable); | ||||
| } | ||||
| 
 | ||||
| static int set_modifier_user(snd_use_case_mgr_t *uc_mgr, | ||||
|                              const char *modifier_name, | ||||
|                              int enable) | ||||
| { | ||||
|         struct use_case_modifier *modifier; | ||||
| 
 | ||||
|         if (uc_mgr->active_verb == NULL) | ||||
|                 return -ENOENT; | ||||
|         modifier = find_modifier(uc_mgr->active_verb, modifier_name); | ||||
|         if (modifier == NULL) | ||||
|                 return -ENOENT; | ||||
|         return set_modifier(uc_mgr, modifier, enable); | ||||
| } | ||||
| 
 | ||||
| static int switch_device(snd_use_case_mgr_t *uc_mgr, | ||||
|                          const char *old_device, | ||||
|                          const char *new_device) | ||||
| { | ||||
|         struct use_case_device *xold, *xnew; | ||||
|         struct transition_sequence *trans; | ||||
|         struct list_head *pos; | ||||
|         int err, seq_found = 0; | ||||
|          | ||||
|         if (uc_mgr->active_verb == NULL) | ||||
|                 return -ENOENT; | ||||
|         if (device_status(uc_mgr, old_device) == 0) { | ||||
|                 uc_error("error: device %s not enabled", old_device); | ||||
|                 return -EINVAL; | ||||
|         } | ||||
|         if (device_status(uc_mgr, new_device) != 0) { | ||||
|                 uc_error("error: device %s already enabled", new_device); | ||||
|                 return -EINVAL; | ||||
|         } | ||||
|         xold = find_device(uc_mgr->active_verb, old_device); | ||||
|         if (xold == NULL) | ||||
|                 return -ENOENT; | ||||
|         xnew = find_device(uc_mgr->active_verb, new_device); | ||||
|         if (xold == NULL) | ||||
|                 return -ENOENT; | ||||
|         err = 0; | ||||
|         list_for_each(pos, &xold->transition_list) { | ||||
|                 trans = list_entry(pos, struct transition_sequence, list); | ||||
|                 if (strcmp(trans->name, new_device) == 0) { | ||||
|                         err = execute_sequence(uc_mgr, &trans->transition_list); | ||||
|                         if (err >= 0) { | ||||
|                                 list_del(&xold->active_list); | ||||
|                                 list_add_tail(&xnew->active_list, &uc_mgr->active_devices); | ||||
|                         } | ||||
|                         seq_found = 1; | ||||
|                         break; | ||||
|                 } | ||||
|         } | ||||
|         if (!seq_found) { | ||||
|                 err = set_device(uc_mgr, xold, 0); | ||||
|                 if (err < 0) | ||||
|                         return err; | ||||
|                 err = set_device(uc_mgr, xnew, 0); | ||||
|                 if (err < 0) | ||||
|                         return err; | ||||
|         } | ||||
|         return err; | ||||
| } | ||||
| 
 | ||||
| static int switch_modifier(snd_use_case_mgr_t *uc_mgr, | ||||
|                            const char *old_modifier, | ||||
|                            const char *new_modifier) | ||||
| { | ||||
|         struct use_case_modifier *xold, *xnew; | ||||
|         struct transition_sequence *trans; | ||||
|         struct list_head *pos; | ||||
|         int err, seq_found = 0; | ||||
|          | ||||
|         if (uc_mgr->active_verb == NULL) | ||||
|                 return -ENOENT; | ||||
|         if (modifier_status(uc_mgr, old_modifier) == 0) { | ||||
|                 uc_error("error: modifier %s not enabled", old_modifier); | ||||
|                 return -EINVAL; | ||||
|         } | ||||
|         if (modifier_status(uc_mgr, new_modifier) != 0) { | ||||
|                 uc_error("error: modifier %s already enabled", new_modifier); | ||||
|                 return -EINVAL; | ||||
|         } | ||||
|         xold = find_modifier(uc_mgr->active_verb, old_modifier); | ||||
|         if (xold == NULL) | ||||
|                 return -ENOENT; | ||||
|         xnew = find_modifier(uc_mgr->active_verb, new_modifier); | ||||
|         if (xold == NULL) | ||||
|                 return -ENOENT; | ||||
|         err = 0; | ||||
|         list_for_each(pos, &xold->transition_list) { | ||||
|                 trans = list_entry(pos, struct transition_sequence, list); | ||||
|                 if (strcmp(trans->name, new_modifier) == 0) { | ||||
|                         err = execute_sequence(uc_mgr, &trans->transition_list); | ||||
|                         if (err >= 0) { | ||||
|                                 list_del(&xold->active_list); | ||||
|                                 list_add_tail(&xnew->active_list, &uc_mgr->active_modifiers); | ||||
|                         } | ||||
|                         seq_found = 1; | ||||
|                         break; | ||||
|                 } | ||||
|         } | ||||
|         if (!seq_found) { | ||||
|                 err = set_modifier(uc_mgr, xold, 0); | ||||
|                 if (err < 0) | ||||
|                         return err; | ||||
|                 err = set_modifier(uc_mgr, xnew, 0); | ||||
|                 if (err < 0) | ||||
|                         return err; | ||||
|         } | ||||
|         return err;         | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief Set new | ||||
|  * \param uc_mgr Use case manager | ||||
|  | @ -961,7 +1173,7 @@ int snd_use_case_set(snd_use_case_mgr_t *uc_mgr, | |||
|                      const char *identifier, | ||||
|                      const char *value) | ||||
| { | ||||
|         char *str, *str1; | ||||
|        char *str, *str1; | ||||
|         int err; | ||||
| 
 | ||||
| 	pthread_mutex_lock(&uc_mgr->mutex); | ||||
|  |  | |||
|  | @ -39,12 +39,8 @@ | |||
| #include "local.h" | ||||
| #include "use-case.h" | ||||
| 
 | ||||
| #define PRE_SEQ			0 | ||||
| #define POST_SEQ		1 | ||||
| #define MAX_FILE		256 | ||||
| #define ALSA_USE_CASE_DIR	ALSA_CONFIG_DIR "/ucm" | ||||
| #define ARRAY_SIZE(x)		(sizeof(x)/sizeof(x[0])) | ||||
| #define VERB_NOT_INITIALISED	-1 | ||||
| 
 | ||||
| #define SEQUENCE_ELEMENT_TYPE_CSET	1 | ||||
| #define SEQUENCE_ELEMENT_TYPE_SLEEP	2 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jaroslav Kysela
						Jaroslav Kysela