mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	* Cleaned the alsa.conf syntax:
- added pcm.front, pcm.rear, pcm.center_lfe blocks * Added configuration for EMU10K1 (it's fully working one!!!) * snd_config_redirect_load->snd_config_refer_load rename * snd_config_search_alias code change (works also with pairs base.key) * cleanups in the evaluate function (the function prototype has been changed)
This commit is contained in:
		
							parent
							
								
									1b8d405606
								
							
						
					
					
						commit
						977a9a33f0
					
				
					 25 changed files with 468 additions and 266 deletions
				
			
		
							
								
								
									
										152
									
								
								src/alsa.conf
									
										
									
									
									
								
							
							
						
						
									
										152
									
								
								src/alsa.conf
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -129,6 +129,156 @@ pcm.default {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pcm.front {
 | 
			
		||||
	args [ CARD DEV ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
		type integer
 | 
			
		||||
		default {
 | 
			
		||||
			@func getenv
 | 
			
		||||
			@type integer
 | 
			
		||||
			envname [
 | 
			
		||||
				ALSA_FRONT_CARD
 | 
			
		||||
				ALSA_PCM_CARD
 | 
			
		||||
				ALSA_CARD
 | 
			
		||||
			]
 | 
			
		||||
			default 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.DEV {
 | 
			
		||||
		type integer
 | 
			
		||||
		default {
 | 
			
		||||
			@func getenv
 | 
			
		||||
			@type integer
 | 
			
		||||
			envname [
 | 
			
		||||
				ALSA_FRONT_DEVICE
 | 
			
		||||
			]
 | 
			
		||||
			default 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	refer {
 | 
			
		||||
		filename {
 | 
			
		||||
			@func concat
 | 
			
		||||
			strings [
 | 
			
		||||
				{
 | 
			
		||||
					@func datadir
 | 
			
		||||
				}
 | 
			
		||||
				"/cards/"
 | 
			
		||||
				{
 | 
			
		||||
					@func card_strtype
 | 
			
		||||
					card $(CARD)
 | 
			
		||||
				}
 | 
			
		||||
				".conf"
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
		name {
 | 
			
		||||
			@func concat
 | 
			
		||||
			strings [
 | 
			
		||||
				"pcm.front_" $(DEV) ":CARD=" $(CARD)
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
pcm.rear {
 | 
			
		||||
	args [ CARD DEV ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
		type integer
 | 
			
		||||
		default {
 | 
			
		||||
			@func getenv
 | 
			
		||||
			@type integer
 | 
			
		||||
			envname [
 | 
			
		||||
				ALSA_REAR_CARD
 | 
			
		||||
				ALSA_PCM_CARD
 | 
			
		||||
				ALSA_CARD
 | 
			
		||||
			]
 | 
			
		||||
			default 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.DEV {
 | 
			
		||||
		type integer
 | 
			
		||||
		default {
 | 
			
		||||
			@func getenv
 | 
			
		||||
			@type integer
 | 
			
		||||
			envname [
 | 
			
		||||
				ALSA_REAR_DEVICE
 | 
			
		||||
			]
 | 
			
		||||
			default 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	refer {
 | 
			
		||||
		filename {
 | 
			
		||||
			@func concat
 | 
			
		||||
			strings [
 | 
			
		||||
				{
 | 
			
		||||
					@func datadir
 | 
			
		||||
				}
 | 
			
		||||
				"/cards/"
 | 
			
		||||
				{
 | 
			
		||||
					@func card_strtype
 | 
			
		||||
					card $(CARD)
 | 
			
		||||
				}
 | 
			
		||||
				".conf"
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
		name {
 | 
			
		||||
			@func concat
 | 
			
		||||
			strings [
 | 
			
		||||
				"pcm.rear_" $(DEV) ":CARD=" $(CARD)
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
pcm.center_lfe {
 | 
			
		||||
	args [ CARD DEV ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
		type integer
 | 
			
		||||
		default {
 | 
			
		||||
			@func getenv
 | 
			
		||||
			@type integer
 | 
			
		||||
			envname [
 | 
			
		||||
				ALSA_CENTER_LFE_CARD
 | 
			
		||||
				ALSA_PCM_CARD
 | 
			
		||||
				ALSA_CARD
 | 
			
		||||
			]
 | 
			
		||||
			default 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	args.DEV {
 | 
			
		||||
		type integer
 | 
			
		||||
		default {
 | 
			
		||||
			@func getenv
 | 
			
		||||
			@type integer
 | 
			
		||||
			envname [
 | 
			
		||||
				ALSA_CENTER_LFE_DEVICE
 | 
			
		||||
			]
 | 
			
		||||
			default 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	refer {
 | 
			
		||||
		filename {
 | 
			
		||||
			@func concat
 | 
			
		||||
			strings [
 | 
			
		||||
				{
 | 
			
		||||
					@func datadir
 | 
			
		||||
				}
 | 
			
		||||
				"/cards/"
 | 
			
		||||
				{
 | 
			
		||||
					@func card_strtype
 | 
			
		||||
					card $(CARD)
 | 
			
		||||
				}
 | 
			
		||||
				".conf"
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
		name {
 | 
			
		||||
			@func concat
 | 
			
		||||
			strings [
 | 
			
		||||
				"pcm.center_lfe_" $(DEV) ":CARD=" $(CARD)
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
pcm.surround40 {
 | 
			
		||||
	args [ CARD DEV ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +454,7 @@ pcm.iec958 {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pcm.spdif iec958
 | 
			
		||||
pcm.spdif pcm.iec958
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
#  Control interface
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
alsadir = $(datadir)/alsa/cards
 | 
			
		||||
cfg_files = SI_7018.conf
 | 
			
		||||
cfg_files = SI_7018.conf EMU10K1.conf
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = $(cfg_files)
 | 
			
		||||
alsa_DATA = $(cfg_files)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
# Configuration for the SI7018 chip
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
pcm.front {
 | 
			
		||||
pcm.si7018_front {
 | 
			
		||||
	args [ CARD DEV SUBDEV ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
		type integer
 | 
			
		||||
| 
						 | 
				
			
			@ -20,12 +20,18 @@ pcm.front {
 | 
			
		|||
	subdevice $(SUBDEV)
 | 
			
		||||
}	
 | 
			
		||||
 | 
			
		||||
pcm_slave.front {
 | 
			
		||||
	pcm pcm.front
 | 
			
		||||
	channels 2
 | 
			
		||||
pcm.front_0 {
 | 
			
		||||
	args [ CARD ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
		type integer
 | 
			
		||||
	}
 | 
			
		||||
	redir {
 | 
			
		||||
		@func concat
 | 
			
		||||
		strings [ "pcm.si7018_front:" $(CARD) ",0,-1" ]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pcm.rear {
 | 
			
		||||
pcm.si7010_rear {
 | 
			
		||||
	args [ CARD DEV SUBDEV ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
		type integer
 | 
			
		||||
| 
						 | 
				
			
			@ -43,12 +49,18 @@ pcm.rear {
 | 
			
		|||
	subdevice $(SUBDEV)
 | 
			
		||||
}	
 | 
			
		||||
 | 
			
		||||
pcm_slave.rear {
 | 
			
		||||
	pcm pcm.rear
 | 
			
		||||
	channels 2
 | 
			
		||||
pcm.rear_0 {
 | 
			
		||||
	args [ CARD ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
		type integer
 | 
			
		||||
	}
 | 
			
		||||
	redir {
 | 
			
		||||
		@func concat
 | 
			
		||||
		strings [ "pcm.si7018_rear:" $(CARD) ",0,-1" ]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pcm.surround40_0_trident_dx_nx {
 | 
			
		||||
pcm.surround40_0 {
 | 
			
		||||
	args [ CARD ]
 | 
			
		||||
	args.CARD {
 | 
			
		||||
		type integer
 | 
			
		||||
| 
						 | 
				
			
			@ -56,16 +68,22 @@ pcm.surround40_0_trident_dx_nx {
 | 
			
		|||
	type multi
 | 
			
		||||
	slaves [
 | 
			
		||||
		{
 | 
			
		||||
			@func concat
 | 
			
		||||
			strings [
 | 
			
		||||
				"pcm_slave.front:" $(CARD) ",0,-1"
 | 
			
		||||
			]
 | 
			
		||||
			pcm {
 | 
			
		||||
				@func concat
 | 
			
		||||
				strings [
 | 
			
		||||
					"pcm.si7018_front:" $(CARD) ",0,-1"
 | 
			
		||||
				]
 | 
			
		||||
			}
 | 
			
		||||
			channels 2
 | 
			
		||||
		}
 | 
			
		||||
		{
 | 
			
		||||
			@func concat
 | 
			
		||||
			strings [
 | 
			
		||||
				"pcm_slave.rear:" $(CARD) ",0,-1"
 | 
			
		||||
			]
 | 
			
		||||
			pcm {
 | 
			
		||||
				@func concat
 | 
			
		||||
				strings [
 | 
			
		||||
					"pcm.si7018_rear:" $(CARD) ",0,-1"
 | 
			
		||||
				]
 | 
			
		||||
			}
 | 
			
		||||
			channels 2
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
	bindings [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										134
									
								
								src/conf.c
									
										
									
									
									
								
							
							
						
						
									
										134
									
								
								src/conf.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1443,8 +1443,9 @@ int snd_config_searchv(snd_config_t *config,
 | 
			
		|||
 * \param result Pointer to found node
 | 
			
		||||
 * \return 0 on success otherwise a negative error code
 | 
			
		||||
 *
 | 
			
		||||
 * If base.key is found and it's a string the value found is recursively
 | 
			
		||||
 * tried instead of suffix.
 | 
			
		||||
 * First key is tried and if nothing is found is tried base.key.
 | 
			
		||||
 * If the value found is a string this is recursively tried in the
 | 
			
		||||
 * same way.
 | 
			
		||||
 */
 | 
			
		||||
int snd_config_search_alias(snd_config_t *config,
 | 
			
		||||
			    const char *base, const char *key,
 | 
			
		||||
| 
						 | 
				
			
			@ -1454,19 +1455,20 @@ int snd_config_search_alias(snd_config_t *config,
 | 
			
		|||
	int err;
 | 
			
		||||
	assert(config && key);
 | 
			
		||||
	if (base) {
 | 
			
		||||
		err = snd_config_searchv(config, &res, base, key, 0);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			return err;
 | 
			
		||||
		while (snd_config_get_string(res, &key) >= 0 &&
 | 
			
		||||
		       snd_config_searchv(config, &res, base, key, 0) >= 0)
 | 
			
		||||
			;
 | 
			
		||||
		err = snd_config_searchv(config, &res, base, key, NULL);
 | 
			
		||||
	} else {
 | 
			
		||||
		err = snd_config_search(config, key, &res);
 | 
			
		||||
	}
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	while (snd_config_get_string(res, &base) >= 0) {
 | 
			
		||||
		err = snd_config_search(config, base, &res);
 | 
			
		||||
		if (err >= 0) {
 | 
			
		||||
			if (snd_config_get_string(res, &key) >= 0)
 | 
			
		||||
				err = snd_config_search(res, key, &res);
 | 
			
		||||
		}
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			return err;
 | 
			
		||||
		while (snd_config_get_string(res, &key) >= 0 &&
 | 
			
		||||
		       snd_config_search(config, key, &res) >= 0)
 | 
			
		||||
			;
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	if (result)
 | 
			
		||||
		*result = res;
 | 
			
		||||
| 
						 | 
				
			
			@ -1926,11 +1928,11 @@ static int evaluate_node(snd_config_t *father, snd_config_t *src,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		char buf[64], *ptr;
 | 
			
		||||
		char buf[64];
 | 
			
		||||
		snd_config_type_t t;
 | 
			
		||||
		snd_config_t *dst = NULL;
 | 
			
		||||
		char *evaluate_name = NULL;
 | 
			
		||||
		int (*evaluate_func)(char **dst, snd_config_t *src, void *private_data);
 | 
			
		||||
		int (*evaluate_func)(snd_config_t **dst, snd_config_t *src, void *private_data);
 | 
			
		||||
		void *h;
 | 
			
		||||
	
 | 
			
		||||
		if (evaluate_name == NULL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1942,64 +1944,82 @@ static int evaluate_node(snd_config_t *father, snd_config_t *src,
 | 
			
		|||
		h = dlopen(lib, RTLD_NOW);
 | 
			
		||||
		if (!h) {
 | 
			
		||||
			SNDERR("Cannot open shared library %s", lib);
 | 
			
		||||
			return -ENOENT;
 | 
			
		||||
			err = -ENOENT;
 | 
			
		||||
			goto __error;
 | 
			
		||||
		}
 | 
			
		||||
		evaluate_func = dlsym(h, evaluate_name);
 | 
			
		||||
		if (!evaluate_func) {
 | 
			
		||||
			dlclose(h);
 | 
			
		||||
			SNDERR("symbol %s is not defined inside %s", evaluate_name, lib ? lib : ALSA_LIB);
 | 
			
		||||
			return -ENXIO;
 | 
			
		||||
			err = -ENXIO;
 | 
			
		||||
			goto __error;
 | 
			
		||||
		}
 | 
			
		||||
		err = evaluate_func(&ptr, src, private_data);
 | 
			
		||||
		err = evaluate_func(&dst, src, private_data);
 | 
			
		||||
		dlclose(h);
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			SNDERR("function %s returned error: %s", evaluate_name, snd_strerror(err));
 | 
			
		||||
			return err;
 | 
			
		||||
			goto __error;
 | 
			
		||||
		}
 | 
			
		||||
		if (type == NULL) {
 | 
			
		||||
			t = SND_CONFIG_TYPE_STRING;
 | 
			
		||||
		} else {
 | 
			
		||||
			err = snd_config_get_type_ascii(type, &t);
 | 
			
		||||
			if (err < 0 || t == SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
			if (err < 0) {
 | 
			
		||||
				err = -EINVAL;
 | 
			
		||||
			      __err:
 | 
			
		||||
				snd_config_delete(dst);
 | 
			
		||||
				goto __error;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (t != snd_config_get_type(dst)) {
 | 
			
		||||
			char *ptr;
 | 
			
		||||
			snd_config_t *n;
 | 
			
		||||
			if (t == SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
				SNDERR("conversion to compound is not supported for field %s", snd_config_get_id(src));
 | 
			
		||||
				err = -EINVAL;
 | 
			
		||||
				goto __err;
 | 
			
		||||
			}
 | 
			
		||||
			err = snd_config_make(&n, snd_config_get_id(dst), t);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				goto __err;
 | 
			
		||||
			err = snd_config_get_ascii(dst, &ptr);
 | 
			
		||||
			if (err < 0) {
 | 
			
		||||
			      __err1:
 | 
			
		||||
				snd_config_delete(n);
 | 
			
		||||
				goto __err;
 | 
			
		||||
			}
 | 
			
		||||
			switch (t) {
 | 
			
		||||
			case SND_CONFIG_TYPE_STRING:
 | 
			
		||||
				n->u.string = ptr;
 | 
			
		||||
				ptr = NULL;
 | 
			
		||||
				err = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case SND_CONFIG_TYPE_INTEGER:
 | 
			
		||||
				{
 | 
			
		||||
					long v;
 | 
			
		||||
					err = safe_strtol(ptr, &v);
 | 
			
		||||
					if (err >= 0)
 | 
			
		||||
						snd_config_set_integer(dst, v);
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
			case SND_CONFIG_TYPE_REAL:
 | 
			
		||||
				{
 | 
			
		||||
					double r;
 | 
			
		||||
					err = safe_strtod(ptr, &r);
 | 
			
		||||
					if (err >= 0)
 | 
			
		||||
						snd_config_set_real(dst, r);
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				err = -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			if (ptr)
 | 
			
		||||
				free(ptr);
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				goto __err1;
 | 
			
		||||
			snd_config_delete(dst);
 | 
			
		||||
			dst = n;
 | 
			
		||||
		}
 | 
			
		||||
		err = snd_config_make(&dst, snd_config_get_id(src), t);
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			free(ptr);
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
		switch (t) {
 | 
			
		||||
		case SND_CONFIG_TYPE_INTEGER:
 | 
			
		||||
			{
 | 
			
		||||
				long v;
 | 
			
		||||
				err = safe_strtol(ptr, &v);
 | 
			
		||||
				if (err < 0) {
 | 
			
		||||
					free(ptr);
 | 
			
		||||
					snd_config_delete(dst);
 | 
			
		||||
					return err;
 | 
			
		||||
				}
 | 
			
		||||
				snd_config_set_integer(dst, v);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case SND_CONFIG_TYPE_REAL:
 | 
			
		||||
			{
 | 
			
		||||
				double r;
 | 
			
		||||
				err = safe_strtod(ptr, &r);
 | 
			
		||||
				if (err < 0) {
 | 
			
		||||
					free(ptr);
 | 
			
		||||
					snd_config_delete(dst);
 | 
			
		||||
					return err;
 | 
			
		||||
				}
 | 
			
		||||
				snd_config_set_real(dst, r);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			snd_config_set_string(dst, ptr);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		free(ptr);
 | 
			
		||||
		*_dst = dst;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			@ -2019,6 +2039,8 @@ int snd_config_evaluate(snd_config_t *conf, void *private_data)
 | 
			
		|||
	snd_config_iterator_t i, next;
 | 
			
		||||
 | 
			
		||||
	assert(conf);
 | 
			
		||||
	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
 | 
			
		||||
		return 0;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -215,11 +215,11 @@ int snd_config_string_replace(const char *src, char idchr,
 | 
			
		|||
 * \param dst_config new configuration block
 | 
			
		||||
 * \param dst_dynamic new configuration block is dynamically allocated
 | 
			
		||||
 */
 | 
			
		||||
int snd_config_redirect_load(snd_config_t *root,
 | 
			
		||||
			     snd_config_t *config,
 | 
			
		||||
			     char **name,
 | 
			
		||||
			     snd_config_t **dst_config,
 | 
			
		||||
			     int *dst_dynamic)
 | 
			
		||||
int snd_config_refer_load(snd_config_t *root,
 | 
			
		||||
			  snd_config_t *config,
 | 
			
		||||
			  char **name,
 | 
			
		||||
			  snd_config_t **dst_config,
 | 
			
		||||
			  int *dst_dynamic)
 | 
			
		||||
{
 | 
			
		||||
	int err, dynamic;
 | 
			
		||||
	snd_config_t *result, *c;
 | 
			
		||||
| 
						 | 
				
			
			@ -303,12 +303,11 @@ int snd_config_redirect_load(snd_config_t *root,
 | 
			
		|||
 *  Helper functions for the configuration file
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int snd_func_getenv(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
int snd_func_getenv(snd_config_t **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
{
 | 
			
		||||
	snd_config_t *n, *d, *e;
 | 
			
		||||
	snd_config_iterator_t i, next;
 | 
			
		||||
	const char *res;
 | 
			
		||||
	char *def = NULL;
 | 
			
		||||
	char *res, *def = NULL;
 | 
			
		||||
	int idx = 0, err;
 | 
			
		||||
	
 | 
			
		||||
	err = snd_config_expand(src, NULL, NULL, &e);
 | 
			
		||||
| 
						 | 
				
			
			@ -361,7 +360,12 @@ int snd_func_getenv(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_
 | 
			
		|||
	def = NULL;
 | 
			
		||||
      __ok:
 | 
			
		||||
	err = res == NULL ? -ENOMEM : 0;
 | 
			
		||||
	*dst = (char *)res;
 | 
			
		||||
	if (err >= 0) {
 | 
			
		||||
		err = snd_config_make_string(dst, snd_config_get_id(src));
 | 
			
		||||
		if (err >= 0)
 | 
			
		||||
			snd_config_set_string(*dst, res);
 | 
			
		||||
		free(res);
 | 
			
		||||
	}
 | 
			
		||||
      __error:
 | 
			
		||||
      	if (def)
 | 
			
		||||
      		free(def);
 | 
			
		||||
| 
						 | 
				
			
			@ -369,7 +373,7 @@ int snd_func_getenv(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_
 | 
			
		|||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int snd_func_concat(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
int snd_func_concat(snd_config_t **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
{
 | 
			
		||||
	snd_config_t *n, *e;
 | 
			
		||||
	snd_config_iterator_t i, next;
 | 
			
		||||
| 
						 | 
				
			
			@ -421,19 +425,20 @@ int snd_func_concat(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_
 | 
			
		|||
		err = -EINVAL;
 | 
			
		||||
		goto __error;
 | 
			
		||||
	}
 | 
			
		||||
	err = 0;
 | 
			
		||||
	*dst = res;
 | 
			
		||||
	err = snd_config_make_string(dst, snd_config_get_id(src));
 | 
			
		||||
	if (err >= 0)
 | 
			
		||||
		snd_config_set_string(*dst, res);
 | 
			
		||||
	free(res);
 | 
			
		||||
      __error:
 | 
			
		||||
	snd_config_delete(e);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int snd_func_datadir(char **dst, snd_config_t *src ATTRIBUTE_UNUSED, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
int snd_func_datadir(snd_config_t **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
{
 | 
			
		||||
	char *res = strdup(DATADIR "/alsa");
 | 
			
		||||
	if (res == NULL)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	*dst = res;
 | 
			
		||||
	int err = snd_config_make_string(dst, snd_config_get_id(src));
 | 
			
		||||
	if (err >= 0)
 | 
			
		||||
		err = snd_config_set_string(*dst, DATADIR "/alsa");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -459,7 +464,7 @@ static int string_from_integer(char **dst, long v)
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int snd_func_card_strtype(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
int snd_func_card_strtype(snd_config_t **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
{
 | 
			
		||||
	snd_config_t *n, *e;
 | 
			
		||||
	char *res = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -497,7 +502,10 @@ int snd_func_card_strtype(char **dst, snd_config_t *src, void *private_data ATTR
 | 
			
		|||
		SNDERR("snd_card_type_enum_to_string failed for %i", (int)snd_ctl_card_info_get_type(info));
 | 
			
		||||
		goto __error;
 | 
			
		||||
	}
 | 
			
		||||
	*dst = res;
 | 
			
		||||
	err = snd_config_make_string(dst, snd_config_get_id(src));
 | 
			
		||||
	if (err >= 0)
 | 
			
		||||
		err = snd_config_set_string(*dst, res);
 | 
			
		||||
	free(res);
 | 
			
		||||
      __error:
 | 
			
		||||
      	if (ctl)
 | 
			
		||||
      		snd_ctl_close(ctl);
 | 
			
		||||
| 
						 | 
				
			
			@ -505,7 +513,7 @@ int snd_func_card_strtype(char **dst, snd_config_t *src, void *private_data ATTR
 | 
			
		|||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int snd_func_card_id(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
int snd_func_card_id(snd_config_t **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
{
 | 
			
		||||
	snd_config_t *n, *e;
 | 
			
		||||
	char *res = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -543,7 +551,10 @@ int snd_func_card_id(char **dst, snd_config_t *src, void *private_data ATTRIBUTE
 | 
			
		|||
		err = -ENOMEM;
 | 
			
		||||
		goto __error;
 | 
			
		||||
	}
 | 
			
		||||
	*dst = res;
 | 
			
		||||
	err = snd_config_make_string(dst, snd_config_get_id(src));
 | 
			
		||||
	if (err >= 0)
 | 
			
		||||
		err = snd_config_set_string(*dst, res);
 | 
			
		||||
	free(res);
 | 
			
		||||
      __error:
 | 
			
		||||
      	if (ctl)
 | 
			
		||||
      		snd_ctl_close(ctl);
 | 
			
		||||
| 
						 | 
				
			
			@ -551,7 +562,7 @@ int snd_func_card_id(char **dst, snd_config_t *src, void *private_data ATTRIBUTE
 | 
			
		|||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int snd_func_pcm_id(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
int snd_func_pcm_id(snd_config_t **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
 | 
			
		||||
{
 | 
			
		||||
	snd_config_t *n, *e;
 | 
			
		||||
	char *res = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -608,7 +619,10 @@ int snd_func_pcm_id(char **dst, snd_config_t *src, void *private_data ATTRIBUTE_
 | 
			
		|||
		err = -ENOMEM;
 | 
			
		||||
		goto __error;
 | 
			
		||||
	}
 | 
			
		||||
	*dst = res;
 | 
			
		||||
	err = snd_config_make_string(dst, snd_config_get_id(src));
 | 
			
		||||
	if (err >= 0)
 | 
			
		||||
		err = snd_config_set_string(*dst, res);
 | 
			
		||||
	free(res);
 | 
			
		||||
      __error:
 | 
			
		||||
      	if (ctl)
 | 
			
		||||
      		snd_ctl_close(ctl);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -459,32 +459,50 @@ int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
 | 
			
		|||
	return open_func(ctlp, name, ctl_conf, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int snd_ctl_open_noupdate(snd_ctl_t **ctlp, const char *name, int mode)
 | 
			
		||||
int snd_ctl_open_noupdate(snd_ctl_t **ctlp, snd_config_t *root, const char *name, int mode)
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
	snd_config_t *ctl_conf;
 | 
			
		||||
	char *base, *key;
 | 
			
		||||
	const char *args = strchr(name, ':');
 | 
			
		||||
	char *base;
 | 
			
		||||
 | 
			
		||||
	if (args) {
 | 
			
		||||
		args++;
 | 
			
		||||
		base = alloca(args - name);
 | 
			
		||||
		memcpy(base, name, args - name - 1);
 | 
			
		||||
		base[args - name - 1] = 0;
 | 
			
		||||
	} else
 | 
			
		||||
		base = (char *) name;
 | 
			
		||||
	err = snd_config_search_alias(snd_config, "ctl", base, &ctl_conf);
 | 
			
		||||
		base[args - name - 1] = '\0';
 | 
			
		||||
		key = strchr(base, '.');
 | 
			
		||||
		if (key)
 | 
			
		||||
			*key++ = '\0';
 | 
			
		||||
	} else {
 | 
			
		||||
		key = strchr(name, '.');
 | 
			
		||||
		if (key) {
 | 
			
		||||
			key++;
 | 
			
		||||
			base = alloca(key - name);
 | 
			
		||||
			memcpy(base, name, key - name - 1);
 | 
			
		||||
			base[key - name - 1] = '\0';
 | 
			
		||||
		} else
 | 
			
		||||
			base = (char *) name;
 | 
			
		||||
	}
 | 
			
		||||
	if (key == NULL) {
 | 
			
		||||
		key = base;
 | 
			
		||||
		base = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_config_search_alias(root, base, key, &ctl_conf);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("Unknown CTL %s", name);
 | 
			
		||||
		(void)(base == NULL && (err = snd_config_search_alias(root, "ctl", key, &ctl_conf)));
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			SNDERR("Unknown PCM %s", name);
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_config_expand(ctl_conf, args, NULL, &ctl_conf);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("Could not expand configuration for %s: %s", name, snd_strerror(err));
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (args) {
 | 
			
		||||
		err = snd_config_expand(ctl_conf, args, NULL, &ctl_conf);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_ctl_open_conf(ctlp, name, ctl_conf, mode);
 | 
			
		||||
	if (args)
 | 
			
		||||
		snd_config_delete(ctl_conf);
 | 
			
		||||
	snd_config_delete(ctl_conf);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -502,7 +520,7 @@ int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode)
 | 
			
		|||
	err = snd_config_update();
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	return snd_ctl_open_noupdate(ctlp, name, mode);
 | 
			
		||||
	return snd_ctl_open_noupdate(ctlp, snd_config, name, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -437,7 +437,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *conf,
 | 
			
		|||
{
 | 
			
		||||
	snd_config_iterator_t i, next;
 | 
			
		||||
	char *tmp;
 | 
			
		||||
	int iface = SND_CTL_ELEM_IFACE_PCM;
 | 
			
		||||
	int iface = SND_CTL_ELEM_IFACE_MIXER;
 | 
			
		||||
	char *name = NULL;
 | 
			
		||||
	long index = 0;
 | 
			
		||||
	long device = -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -452,7 +452,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *conf,
 | 
			
		|||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
		if (strcmp(id, "comment") == 0)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (strcmp(id, "iface") == 0) {
 | 
			
		||||
		if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) {
 | 
			
		||||
			if ((err = config_replace(n, callback, private_data, &tmp)) < 0)
 | 
			
		||||
				goto _err;
 | 
			
		||||
			if ((err = snd_config_get_ctl_iface_ascii(tmp)) < 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -471,6 +471,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *conf,
 | 
			
		|||
		if (strcmp(id, "index") == 0) {
 | 
			
		||||
			if ((err = config_replace_integer(n, callback, private_data, &index)) < 0)
 | 
			
		||||
				goto _err;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (strcmp(id, "device") == 0) {
 | 
			
		||||
			if ((err = config_replace_integer(n, callback, private_data, &device)) < 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -544,7 +545,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *conf,
 | 
			
		|||
	snd_ctl_elem_info_set_id(elem->info, elem->id);
 | 
			
		||||
	err = snd_ctl_elem_info(h->ctl, elem->info);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("Cannot obtain info for CTL elem");
 | 
			
		||||
		SNDERR("Cannot obtain info for CTL elem (%s,'%s',%li,%li,%li): %s", snd_ctl_elem_iface_name(iface), name, index, device, subdevice, snd_strerror(err));
 | 
			
		||||
		goto _err;
 | 
			
		||||
	}
 | 
			
		||||
	snd_ctl_elem_value_set_id(elem->val, elem->id);
 | 
			
		||||
| 
						 | 
				
			
			@ -597,6 +598,7 @@ int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf,
 | 
			
		|||
	int err;
 | 
			
		||||
 | 
			
		||||
	assert(sctl);
 | 
			
		||||
	assert(handle);
 | 
			
		||||
	assert(conf);
 | 
			
		||||
	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1001,9 +1001,8 @@ static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
 | 
			
		|||
{
 | 
			
		||||
	int err;
 | 
			
		||||
	snd_config_t *pcm_conf;
 | 
			
		||||
	char *key;
 | 
			
		||||
	char *base, *key;
 | 
			
		||||
	const char *args = strchr(name, ':');
 | 
			
		||||
	char *base;
 | 
			
		||||
	snd_config_t *conf;
 | 
			
		||||
	if (args) {
 | 
			
		||||
		args++;
 | 
			
		||||
| 
						 | 
				
			
			@ -1037,23 +1036,23 @@ static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
 | 
			
		|||
	}
 | 
			
		||||
	err = snd_config_expand(pcm_conf, args, NULL, &pcm_conf);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("Could not expand configuration: %s", snd_strerror(err));
 | 
			
		||||
		SNDERR("Could not expand configuration for %s: %s", name, snd_strerror(err));
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (snd_config_search(pcm_conf, "refer", &conf) >= 0) {
 | 
			
		||||
		snd_config_t *tmp_conf;
 | 
			
		||||
		int conf_free_tmp;
 | 
			
		||||
		char *redir_name = NULL;
 | 
			
		||||
		err = snd_config_redirect_load(root, conf, &redir_name, &tmp_conf, &conf_free_tmp);
 | 
			
		||||
		char *refer_name = NULL;
 | 
			
		||||
		err = snd_config_refer_load(root, conf, &refer_name, &tmp_conf, &conf_free_tmp);
 | 
			
		||||
		if (args)
 | 
			
		||||
			snd_config_delete(pcm_conf);
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			SNDERR("Redirect error: %s", snd_strerror(err));
 | 
			
		||||
			SNDERR("Refer load error for %s: %s", name, snd_strerror(err));
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
		err = snd_pcm_open_noupdate(pcmp, tmp_conf, redir_name, stream, mode);
 | 
			
		||||
		if (redir_name)
 | 
			
		||||
			free(redir_name);
 | 
			
		||||
		err = snd_pcm_open_noupdate(pcmp, tmp_conf, refer_name, stream, mode);
 | 
			
		||||
		if (refer_name)
 | 
			
		||||
			free(refer_name);
 | 
			
		||||
		if (conf_free_tmp)
 | 
			
		||||
			snd_config_delete(tmp_conf);
 | 
			
		||||
		return err;
 | 
			
		||||
| 
						 | 
				
			
			@ -1083,25 +1082,13 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#ifndef DOC_HIDDEN
 | 
			
		||||
int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root, snd_config_t *conf,
 | 
			
		||||
		       const char *args, snd_pcm_stream_t stream, int mode)
 | 
			
		||||
int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
 | 
			
		||||
		       snd_config_t *conf, snd_pcm_stream_t stream,
 | 
			
		||||
		       int mode)
 | 
			
		||||
{
 | 
			
		||||
	const char *str;
 | 
			
		||||
	if (snd_config_get_string(conf, &str) >= 0) {
 | 
			
		||||
		char *tmp;
 | 
			
		||||
		int err;
 | 
			
		||||
		if (args == NULL)
 | 
			
		||||
			return snd_pcm_open_noupdate(pcmp, root, str, stream, mode);
 | 
			
		||||
		tmp = malloc(strlen(str) + 1 + strlen(args) + 1);
 | 
			
		||||
		if (tmp == NULL)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		strcpy(tmp, str);
 | 
			
		||||
		strcat(tmp, ":");
 | 
			
		||||
		strcat(tmp, args);
 | 
			
		||||
		err = snd_pcm_open_noupdate(pcmp, root, tmp, stream, mode);
 | 
			
		||||
		free(tmp);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (snd_config_get_string(conf, &str) >= 0)
 | 
			
		||||
		return snd_pcm_open_noupdate(pcmp, root, str, stream, mode);
 | 
			
		||||
	return snd_pcm_open_conf(pcmp, NULL, root, conf, stream, mode);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -4318,8 +4305,7 @@ static const char *names[SND_PCM_HW_PARAM_LAST + 1] = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
 | 
			
		||||
		       snd_config_t **pcm_conf, const char **pcm_args,
 | 
			
		||||
		       unsigned int count, ...)
 | 
			
		||||
		       snd_config_t **_pcm_conf, unsigned int count, ...)
 | 
			
		||||
{
 | 
			
		||||
	snd_config_iterator_t i, next;
 | 
			
		||||
	const char *str;
 | 
			
		||||
| 
						 | 
				
			
			@ -4330,48 +4316,18 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
 | 
			
		|||
		int valid;
 | 
			
		||||
	} fields[count];
 | 
			
		||||
	unsigned int k;
 | 
			
		||||
	int pcm_valid = 0;
 | 
			
		||||
	snd_config_t *pcm_conf = NULL;
 | 
			
		||||
	int err;
 | 
			
		||||
	va_list args;
 | 
			
		||||
	assert(root);
 | 
			
		||||
	assert(conf);
 | 
			
		||||
	assert(pcm_conf);
 | 
			
		||||
	assert(_pcm_conf);
 | 
			
		||||
	if (snd_config_get_string(conf, &str) >= 0) {
 | 
			
		||||
		char *key;
 | 
			
		||||
		const char *args = strchr(str, ':');
 | 
			
		||||
		char *base;
 | 
			
		||||
		if (args) {
 | 
			
		||||
			args++;
 | 
			
		||||
			base = alloca(args - str);
 | 
			
		||||
			memcpy(base, str, args - str - 1);
 | 
			
		||||
			base[args - str - 1] = '\0';
 | 
			
		||||
			key = strchr(base, '.');
 | 
			
		||||
			if (key)
 | 
			
		||||
				*key++ = '\0';
 | 
			
		||||
		} else {
 | 
			
		||||
			key = strchr(str, '.');
 | 
			
		||||
			if (key) {
 | 
			
		||||
				key++;
 | 
			
		||||
				base = alloca(key - str);
 | 
			
		||||
				memcpy(base, str, key - str - 1);
 | 
			
		||||
				base[key - str - 1] = '\0';
 | 
			
		||||
			} else
 | 
			
		||||
				base = (char *) str;
 | 
			
		||||
		}
 | 
			
		||||
		if (key == NULL) {
 | 
			
		||||
			key = base;
 | 
			
		||||
			base = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		err = snd_config_search_alias(root, base, key, &conf);
 | 
			
		||||
		err = snd_config_search_alias(conf, "pcm_slave", str, &conf);
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			(void)(base == NULL && (err = snd_config_search_alias(root, "pcm_slave", key, &conf)));
 | 
			
		||||
			if (err < 0) {
 | 
			
		||||
				SNDERR("unknown pcm_slave %s", str);
 | 
			
		||||
				return err;
 | 
			
		||||
			}
 | 
			
		||||
			SNDERR("Configuration pcm_slave.%s was not found\n", str);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		if (pcm_args)
 | 
			
		||||
			*pcm_args = args;
 | 
			
		||||
	}
 | 
			
		||||
	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
 | 
			
		||||
		SNDERR("Invalid slave definition");
 | 
			
		||||
| 
						 | 
				
			
			@ -4391,8 +4347,7 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
 | 
			
		|||
		if (strcmp(id, "comment") == 0)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (strcmp(id, "pcm") == 0) {
 | 
			
		||||
			*pcm_conf = n;
 | 
			
		||||
			pcm_valid = 1;
 | 
			
		||||
			pcm_conf = n;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		for (k = 0; k < count; ++k) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4435,7 +4390,7 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
 | 
			
		|||
		SNDERR("Unknown field %s", id);
 | 
			
		||||
		// return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	if (!pcm_valid) {
 | 
			
		||||
	if (!pcm_conf) {
 | 
			
		||||
		SNDERR("missing field pcm");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -4445,6 +4400,7 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
 | 
			
		|||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*_pcm_conf = pcm_conf;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
		
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -556,7 +556,6 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_pcm_t *spcm;
 | 
			
		||||
	snd_config_t *slave = NULL, *sconf;
 | 
			
		||||
	snd_pcm_format_t sformat;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -573,7 +572,7 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 1,
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 1,
 | 
			
		||||
				 SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
| 
						 | 
				
			
			@ -582,7 +581,7 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("invalid slave format");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_adpcm_open(pcmp, name, sformat, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -429,7 +429,6 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_pcm_t *spcm;
 | 
			
		||||
	snd_config_t *slave = NULL, *sconf;
 | 
			
		||||
	snd_pcm_format_t sformat;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -446,7 +445,7 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 1,
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 1,
 | 
			
		||||
				 SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
| 
						 | 
				
			
			@ -455,7 +454,7 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("invalid slave format");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_alaw_open(pcmp, name, sformat, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -198,7 +198,6 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	int err;
 | 
			
		||||
	snd_pcm_t *spcm;
 | 
			
		||||
	snd_config_t *slave = NULL, *sconf;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -215,10 +214,10 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 0);
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 0);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_copy_open(pcmp, name, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -466,7 +466,6 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	const char *fname = NULL;
 | 
			
		||||
	const char *format = NULL;
 | 
			
		||||
	long fd = -1;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -502,14 +501,14 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 0);
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 0);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	if (!fname && fd < 0) {
 | 
			
		||||
		SNDERR("file is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_file_open(pcmp, name, fname, fd, format, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -355,7 +355,7 @@ int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *conf)
 | 
			
		|||
			type = n;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (strcmp(id, "args") == 0) {
 | 
			
		||||
		if (strcmp(id, "hook_args") == 0) {
 | 
			
		||||
			args = n;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -441,7 +441,6 @@ int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_pcm_t *spcm;
 | 
			
		||||
	snd_config_t *slave = NULL, *sconf;
 | 
			
		||||
	snd_config_t *hooks = NULL;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -466,10 +465,10 @@ int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 0);
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 0);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_hooks_open(pcmp, name, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -334,7 +334,6 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_pcm_t *spcm;
 | 
			
		||||
	snd_config_t *slave = NULL, *sconf;
 | 
			
		||||
	snd_pcm_format_t sformat;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -351,7 +350,7 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 1,
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 1,
 | 
			
		||||
				 SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
| 
						 | 
				
			
			@ -359,7 +358,7 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave format is not linear");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_linear_open(pcmp, name, sformat, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -527,11 +527,12 @@ int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy, int orde
 | 
			
		|||
				       snd_pcm_hw_strategy_simple_choices_list_t *choices);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf, snd_config_t **pcm_conf,
 | 
			
		||||
		       const char **args, unsigned int count, ...);
 | 
			
		||||
int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
 | 
			
		||||
		       snd_config_t **pcm_conf, unsigned int count, ...);
 | 
			
		||||
 | 
			
		||||
int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root, snd_config_t *conf,
 | 
			
		||||
		       const char *args, snd_pcm_stream_t stream, int mode);
 | 
			
		||||
int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
 | 
			
		||||
		       snd_config_t *conf, snd_pcm_stream_t stream,
 | 
			
		||||
		       int mode);
 | 
			
		||||
int snd_pcm_conf_generic_id(const char *id);
 | 
			
		||||
 | 
			
		||||
#define SND_PCM_HW_PARBIT_ACCESS	(1U << SND_PCM_HW_PARAM_ACCESS)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -743,7 +743,6 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_config_t *slave = NULL, *sconf;
 | 
			
		||||
	long frequency = -1;
 | 
			
		||||
	snd_config_t *scopes = NULL;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -776,10 +775,10 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 0);
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 0);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_meter_open(pcmp, name, frequency > 0 ? (unsigned int) frequency : FREQUENCY, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -444,7 +444,6 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_pcm_t *spcm;
 | 
			
		||||
	snd_config_t *slave = NULL, *sconf;
 | 
			
		||||
	snd_pcm_format_t sformat;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -461,7 +460,7 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 1,
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 1,
 | 
			
		||||
				 SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
| 
						 | 
				
			
			@ -470,7 +469,7 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("invalid slave format");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_mulaw_open(pcmp, name, sformat, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -659,7 +659,6 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	unsigned int idx;
 | 
			
		||||
	const char **slaves_id = NULL;
 | 
			
		||||
	snd_config_t **slaves_conf = NULL;
 | 
			
		||||
	const char **slaves_args = NULL;
 | 
			
		||||
	snd_pcm_t **slaves_pcm = NULL;
 | 
			
		||||
	unsigned int *slaves_channels = NULL;
 | 
			
		||||
	int *channels_sidx = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -731,7 +730,6 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	}
 | 
			
		||||
	slaves_id = calloc(slaves_count, sizeof(*slaves_id));
 | 
			
		||||
	slaves_conf = calloc(slaves_count, sizeof(*slaves_conf));
 | 
			
		||||
	slaves_args = calloc(slaves_count, sizeof(*slaves_args));
 | 
			
		||||
	slaves_pcm = calloc(slaves_count, sizeof(*slaves_pcm));
 | 
			
		||||
	slaves_channels = calloc(slaves_count, sizeof(*slaves_channels));
 | 
			
		||||
	channels_sidx = calloc(channels_count, sizeof(*channels_sidx));
 | 
			
		||||
| 
						 | 
				
			
			@ -744,7 +742,7 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		snd_config_t *m = snd_config_iterator_entry(i);
 | 
			
		||||
		int channels;
 | 
			
		||||
		slaves_id[idx] = snd_config_get_id(m);
 | 
			
		||||
		err = snd_pcm_slave_conf(root, m, &slaves_conf[idx], &slaves_args[idx], 1,
 | 
			
		||||
		err = snd_pcm_slave_conf(root, m, &slaves_conf[idx], 1,
 | 
			
		||||
					 SND_PCM_HW_PARAM_CHANNELS, 1, &channels);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			goto _free;
 | 
			
		||||
| 
						 | 
				
			
			@ -818,7 +816,7 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	}
 | 
			
		||||
	
 | 
			
		||||
	for (idx = 0; idx < slaves_count; ++idx) {
 | 
			
		||||
		err = snd_pcm_open_slave(&slaves_pcm[idx], root, slaves_conf[idx], slaves_args[idx], stream, mode);
 | 
			
		||||
		err = snd_pcm_open_slave(&slaves_pcm[idx], root, slaves_conf[idx], stream, mode);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			goto _free;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -836,8 +834,6 @@ _free:
 | 
			
		|||
	}
 | 
			
		||||
	if (slaves_conf)
 | 
			
		||||
		free(slaves_conf);
 | 
			
		||||
	if (slaves_args)
 | 
			
		||||
		free(slaves_args);
 | 
			
		||||
	if (slaves_pcm)
 | 
			
		||||
		free(slaves_pcm);
 | 
			
		||||
	if (slaves_channels)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -721,7 +721,6 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_config_t *tt = NULL;
 | 
			
		||||
	snd_pcm_route_ttable_entry_t *ttable = NULL;
 | 
			
		||||
	unsigned int cused, sused;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -746,7 +745,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 0);
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 0);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	if (tt) {
 | 
			
		||||
| 
						 | 
				
			
			@ -757,7 +756,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_plug_open(pcmp, name, ttable, MAX_CHANNELS, cused, sused, spcm, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -544,7 +544,6 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_config_t *slave = NULL, *sconf;
 | 
			
		||||
	snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
 | 
			
		||||
	int srate = -1;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -561,7 +560,7 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 2,
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 2,
 | 
			
		||||
				 SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
 | 
			
		||||
				 SND_PCM_HW_PARAM_RATE, 1, &srate);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -571,7 +570,7 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("slave format is not linear");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_rate_open(pcmp, name, 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -848,7 +848,6 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	snd_config_t *tt = NULL;
 | 
			
		||||
	snd_pcm_route_ttable_entry_t ttable[MAX_CHANNELS*MAX_CHANNELS];
 | 
			
		||||
	unsigned int cused, sused;
 | 
			
		||||
	const char *args;
 | 
			
		||||
	snd_config_for_each(i, next, conf) {
 | 
			
		||||
		snd_config_t *n = snd_config_iterator_entry(i);
 | 
			
		||||
		const char *id = snd_config_get_id(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -877,7 +876,7 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
		SNDERR("ttable is not defined");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, &args, 2,
 | 
			
		||||
	err = snd_pcm_slave_conf(root, slave, &sconf, 2,
 | 
			
		||||
				 SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
 | 
			
		||||
				 SND_PCM_HW_PARAM_CHANNELS, 0, &schannels);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -893,7 +892,7 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
 | 
			
		|||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, args, stream, mode);
 | 
			
		||||
	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	err = snd_pcm_route_open(pcmp, name, sformat, schannels,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -156,32 +156,50 @@ int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
 | 
			
		||||
			      const char *name, int mode)
 | 
			
		||||
			      snd_config_t *root, const char *name, int mode)
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
	snd_config_t *rawmidi_conf;
 | 
			
		||||
	char *base, *key;
 | 
			
		||||
	const char *args = strchr(name, ':');
 | 
			
		||||
	char *base;
 | 
			
		||||
 | 
			
		||||
	if (args) {
 | 
			
		||||
		args++;
 | 
			
		||||
		base = alloca(args - name);
 | 
			
		||||
		memcpy(base, name, args - name - 1);
 | 
			
		||||
		base[args - name - 1] = 0;
 | 
			
		||||
	} else
 | 
			
		||||
		base = (char *) name;
 | 
			
		||||
	err = snd_config_search_alias(snd_config, "rawmidi", base, &rawmidi_conf);
 | 
			
		||||
		base[args - name - 1] = '\0';
 | 
			
		||||
		key = strchr(base, '.');
 | 
			
		||||
		if (key)
 | 
			
		||||
			*key++ = '\0';
 | 
			
		||||
	} else {
 | 
			
		||||
		key = strchr(name, '.');
 | 
			
		||||
		if (key) {
 | 
			
		||||
			key++;
 | 
			
		||||
			base = alloca(key - name);
 | 
			
		||||
			memcpy(base, name, key - name - 1);
 | 
			
		||||
			base[key - name - 1] = '\0';
 | 
			
		||||
		} else
 | 
			
		||||
			base = (char *) name;
 | 
			
		||||
	}
 | 
			
		||||
	if (key == NULL) {
 | 
			
		||||
		key = base;
 | 
			
		||||
		base = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_config_search_alias(root, base, key, &rawmidi_conf);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("Unknown RAWMIDI %s", name);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (args) {
 | 
			
		||||
		err = snd_config_expand(rawmidi_conf, args, NULL, &rawmidi_conf);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
		(void)(base == NULL && (err = snd_config_search_alias(root, "rawmidi", key, &rawmidi_conf)));
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			SNDERR("Unknown RawMidi %s", name);
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_config_expand(rawmidi_conf, args, NULL, &rawmidi_conf);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("Could not expand configuration for %s: %s", name, snd_strerror(err));
 | 
			
		||||
		return err;
 | 
			
		||||
        }
 | 
			
		||||
	err = snd_rawmidi_open_conf(inputp, outputp, name, rawmidi_conf, mode);
 | 
			
		||||
	if (args)
 | 
			
		||||
		snd_config_delete(rawmidi_conf);
 | 
			
		||||
	snd_config_delete(rawmidi_conf);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -204,7 +222,7 @@ int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
 | 
			
		|||
	err = snd_config_update();
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	return snd_rawmidi_open_noupdate(inputp, outputp, name, mode);
 | 
			
		||||
	return snd_rawmidi_open_noupdate(inputp, outputp, snd_config, name, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,33 +141,51 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name,
 | 
			
		|||
	return open_func(seqp, name, seq_conf, streams, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int snd_seq_open_noupdate(snd_seq_t **seqp, const char *name, 
 | 
			
		||||
				 int streams, int mode)
 | 
			
		||||
static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root,
 | 
			
		||||
				 const char *name, int streams, int mode)
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
	snd_config_t *seq_conf;
 | 
			
		||||
	char *base, *key;
 | 
			
		||||
	const char *args = strchr(name, ':');
 | 
			
		||||
	char *base;
 | 
			
		||||
 | 
			
		||||
	if (args) {
 | 
			
		||||
		args++;
 | 
			
		||||
		base = alloca(args - name);
 | 
			
		||||
		memcpy(base, name, args - name - 1);
 | 
			
		||||
		base[args - name - 1] = 0;
 | 
			
		||||
	} else
 | 
			
		||||
		base = (char *) name;
 | 
			
		||||
	err = snd_config_search_alias(snd_config, "seq", base, &seq_conf);
 | 
			
		||||
		base[args - name - 1] = '\0';
 | 
			
		||||
		key = strchr(base, '.');
 | 
			
		||||
		if (key)
 | 
			
		||||
			*key++ = '\0';
 | 
			
		||||
	} else {
 | 
			
		||||
		key = strchr(name, '.');
 | 
			
		||||
		if (key) {
 | 
			
		||||
			key++;
 | 
			
		||||
			base = alloca(key - name);
 | 
			
		||||
			memcpy(base, name, key - name - 1);
 | 
			
		||||
			base[key - name - 1] = '\0';
 | 
			
		||||
		} else
 | 
			
		||||
			base = (char *) name;
 | 
			
		||||
	}
 | 
			
		||||
	if (key == NULL) {
 | 
			
		||||
		key = base;
 | 
			
		||||
		base = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_config_search_alias(root, base, key, &seq_conf);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("Unknown SEQ %s", name);
 | 
			
		||||
		(void)(base == NULL && (err = snd_config_search_alias(root, "seq", key, &seq_conf)));
 | 
			
		||||
		if (err < 0) {
 | 
			
		||||
			SNDERR("Unknown PCM %s", name);
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_config_expand(seq_conf, args, NULL, &seq_conf);
 | 
			
		||||
	if (err < 0) {
 | 
			
		||||
		SNDERR("Could not expand configuration for %s: %s", name, snd_strerror(err));
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (args) {
 | 
			
		||||
		err = snd_config_expand(seq_conf, args, NULL, &seq_conf);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
	err = snd_seq_open_conf(seqp, name, seq_conf, streams, mode);
 | 
			
		||||
	if (args)
 | 
			
		||||
		snd_config_delete(seq_conf);
 | 
			
		||||
	snd_config_delete(seq_conf);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -209,7 +227,7 @@ int snd_seq_open(snd_seq_t **seqp, const char *name,
 | 
			
		|||
	err = snd_config_update();
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
	return snd_seq_open_noupdate(seqp, name, streams, mode);
 | 
			
		||||
	return snd_seq_open_noupdate(seqp, snd_config, name, streams, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue