mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	macro->refer
Added the @hooks code...
This commit is contained in:
		
							parent
							
								
									d5a5a79a03
								
							
						
					
					
						commit
						1c14c13c96
					
				
					 3 changed files with 376 additions and 165 deletions
				
			
		| 
						 | 
					@ -4,12 +4,16 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# preload configuration files
 | 
					# preload configuration files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
preload {
 | 
					@hooks [
 | 
				
			||||||
	filenames [
 | 
						{
 | 
				
			||||||
 | 
							func load
 | 
				
			||||||
 | 
							files [
 | 
				
			||||||
			"/etc/asound.conf"
 | 
								"/etc/asound.conf"
 | 
				
			||||||
			"~/.asoundrc"
 | 
								"~/.asoundrc"
 | 
				
			||||||
		]
 | 
							]
 | 
				
			||||||
 | 
							errors false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# defaults
 | 
					# defaults
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +48,7 @@ pcm.hw {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.card
 | 
									name defaults.pcm.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -57,7 +61,7 @@ pcm.hw {
 | 
				
			||||||
				ALSA_PCM_DEVICE
 | 
									ALSA_PCM_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.device
 | 
									name defaults.pcm.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -65,7 +69,7 @@ pcm.hw {
 | 
				
			||||||
	@args.SUBDEV {
 | 
						@args.SUBDEV {
 | 
				
			||||||
		type integer
 | 
							type integer
 | 
				
			||||||
		default {
 | 
							default {
 | 
				
			||||||
			@func macro
 | 
								@func refer
 | 
				
			||||||
			name defaults.pcm.subdevice
 | 
								name defaults.pcm.subdevice
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}		
 | 
						}		
 | 
				
			||||||
| 
						 | 
					@ -86,7 +90,7 @@ pcm.plughw {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.card
 | 
									name defaults.pcm.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -99,7 +103,7 @@ pcm.plughw {
 | 
				
			||||||
				ALSA_PCM_DEVICE
 | 
									ALSA_PCM_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.device
 | 
									name defaults.pcm.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -107,7 +111,7 @@ pcm.plughw {
 | 
				
			||||||
	@args.SUBDEV {
 | 
						@args.SUBDEV {
 | 
				
			||||||
		type integer
 | 
							type integer
 | 
				
			||||||
		default {
 | 
							default {
 | 
				
			||||||
			@func macro
 | 
								@func refer
 | 
				
			||||||
			name defaults.pcm.subdevice
 | 
								name defaults.pcm.subdevice
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}		
 | 
						}		
 | 
				
			||||||
| 
						 | 
					@ -190,7 +194,7 @@ pcm.default {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.card
 | 
									name defaults.pcm.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -200,12 +204,12 @@ pcm.default {
 | 
				
			||||||
				ALSA_PCM_DEVICE
 | 
									ALSA_PCM_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.device
 | 
									name defaults.pcm.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		subdevice {
 | 
							subdevice {
 | 
				
			||||||
			@func macro
 | 
								@func refer
 | 
				
			||||||
			name defaults.pcm.subdevice
 | 
								name defaults.pcm.subdevice
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -223,7 +227,7 @@ pcm.front {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.front.card
 | 
									name defaults.pcm.front.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -236,7 +240,7 @@ pcm.front {
 | 
				
			||||||
				ALSA_FRONT_DEVICE
 | 
									ALSA_FRONT_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.front.device
 | 
									name defaults.pcm.front.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -281,7 +285,7 @@ pcm.rear {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.rear.card
 | 
									name defaults.pcm.rear.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -294,7 +298,7 @@ pcm.rear {
 | 
				
			||||||
				ALSA_REAR_DEVICE
 | 
									ALSA_REAR_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.rear.device
 | 
									name defaults.pcm.rear.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -339,7 +343,7 @@ pcm.center_lfe {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.center_lfe.card
 | 
									name defaults.pcm.center_lfe.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -352,7 +356,7 @@ pcm.center_lfe {
 | 
				
			||||||
				ALSA_CENTER_LFE_DEVICE
 | 
									ALSA_CENTER_LFE_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.center_lfe.device
 | 
									name defaults.pcm.center_lfe.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -397,7 +401,7 @@ pcm.surround40 {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.surround40.card
 | 
									name defaults.pcm.surround40.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -410,7 +414,7 @@ pcm.surround40 {
 | 
				
			||||||
				ALSA_SURROUND40_DEVICE
 | 
									ALSA_SURROUND40_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.surround40.device
 | 
									name defaults.pcm.surround40.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -455,7 +459,7 @@ pcm.surround51 {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.surround51.card
 | 
									name defaults.pcm.surround51.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -468,7 +472,7 @@ pcm.surround51 {
 | 
				
			||||||
				ALSA_SURROUND51_DEVICE
 | 
									ALSA_SURROUND51_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.surround51.device
 | 
									name defaults.pcm.surround51.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -513,7 +517,7 @@ pcm.iec958 {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.iec958.card
 | 
									name defaults.pcm.iec958.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -526,7 +530,7 @@ pcm.iec958 {
 | 
				
			||||||
				ALSA_IEC958_DEVICE
 | 
									ALSA_IEC958_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.pcm.iec958.device
 | 
									name defaults.pcm.iec958.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -601,7 +605,7 @@ ctl.hw {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.ctl.card
 | 
									name defaults.ctl.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -632,7 +636,7 @@ ctl.default {
 | 
				
			||||||
			ALSA_CARD
 | 
								ALSA_CARD
 | 
				
			||||||
		]
 | 
							]
 | 
				
			||||||
		default {
 | 
							default {
 | 
				
			||||||
			@func macro
 | 
								@func refer
 | 
				
			||||||
			name defaults.ctl.card
 | 
								name defaults.ctl.card
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -653,7 +657,7 @@ rawmidi.hw {
 | 
				
			||||||
				ALSA_CARD
 | 
									ALSA_CARD
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.rawmidi.card
 | 
									name defaults.rawmidi.card
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -666,7 +670,7 @@ rawmidi.hw {
 | 
				
			||||||
				ALSA_RAWMIDI_DEVICE
 | 
									ALSA_RAWMIDI_DEVICE
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
			default {
 | 
								default {
 | 
				
			||||||
				@func macro
 | 
									@func refer
 | 
				
			||||||
				name defaults.rawmidi.device
 | 
									name defaults.rawmidi.device
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -690,7 +694,7 @@ rawmidi.default {
 | 
				
			||||||
			ALSA_CARD
 | 
								ALSA_CARD
 | 
				
			||||||
		]
 | 
							]
 | 
				
			||||||
		default {
 | 
							default {
 | 
				
			||||||
			@func macro
 | 
								@func refer
 | 
				
			||||||
			name defaults.rawmidi.card
 | 
								name defaults.rawmidi.card
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -700,7 +704,7 @@ rawmidi.default {
 | 
				
			||||||
			ALSA_RAWMIDI_DEVICE
 | 
								ALSA_RAWMIDI_DEVICE
 | 
				
			||||||
		]
 | 
							]
 | 
				
			||||||
		default {
 | 
							default {
 | 
				
			||||||
			@func macro
 | 
								@func refer
 | 
				
			||||||
			name defaults.rawmidi.device
 | 
								name defaults.rawmidi.device
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										463
									
								
								src/conf.c
									
										
									
									
									
								
							
							
						
						
									
										463
									
								
								src/conf.c
									
										
									
									
									
								
							| 
						 | 
					@ -397,6 +397,7 @@ static int get_string(char **string, int id, input_t *input)
 | 
				
			||||||
static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
 | 
					static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_config_t *n;
 | 
						snd_config_t *n;
 | 
				
			||||||
 | 
						assert(config);
 | 
				
			||||||
	n = calloc(1, sizeof(*n));
 | 
						n = calloc(1, sizeof(*n));
 | 
				
			||||||
	if (n == NULL) {
 | 
						if (n == NULL) {
 | 
				
			||||||
		if (*id) {
 | 
							if (*id) {
 | 
				
			||||||
| 
						 | 
					@ -902,6 +903,31 @@ static int _snd_config_save_leaves(snd_config_t *config, snd_output_t *out, unsi
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Substitute one node to another
 | 
				
			||||||
 | 
					 * \brief dst Destination node
 | 
				
			||||||
 | 
					 * \brief src Source node (invalid after cal)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						assert(dst && src);
 | 
				
			||||||
 | 
						if (src->type == SND_CONFIG_TYPE_COMPOUND) {
 | 
				
			||||||
 | 
							snd_config_iterator_t i, next;
 | 
				
			||||||
 | 
							snd_config_for_each(i, next, src) {
 | 
				
			||||||
 | 
								snd_config_t *n = snd_config_iterator_entry(i);
 | 
				
			||||||
 | 
								n->father = dst;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							src->u.compound.fields.next->prev = &dst->u.compound.fields;
 | 
				
			||||||
 | 
							src->u.compound.fields.prev->next = &dst->u.compound.fields;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(dst->id);
 | 
				
			||||||
 | 
						dst->id  = src->id;
 | 
				
			||||||
 | 
						dst->type = src->type;
 | 
				
			||||||
 | 
						dst->u = src->u;
 | 
				
			||||||
 | 
						free(src);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * \brief Return type of a config node from an ASCII string
 | 
					 * \brief Return type of a config node from an ASCII string
 | 
				
			||||||
 * \param config Config node handle
 | 
					 * \param config Config node handle
 | 
				
			||||||
| 
						 | 
					@ -1065,6 +1091,20 @@ int snd_config_add(snd_config_t *father, snd_config_t *leaf)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Remove a leaf config node from tree
 | 
				
			||||||
 | 
					 * \param config Config node handle
 | 
				
			||||||
 | 
					 * \return 0 on success otherwise a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int snd_config_remove(snd_config_t *config)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						assert(config);
 | 
				
			||||||
 | 
						if (config->father)
 | 
				
			||||||
 | 
							list_del(&config->list);
 | 
				
			||||||
 | 
						config->father = NULL;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * \brief Remove a leaf config node (freeing all the related resources)
 | 
					 * \brief Remove a leaf config node (freeing all the related resources)
 | 
				
			||||||
 * \param config Config node handle
 | 
					 * \param config Config node handle
 | 
				
			||||||
| 
						 | 
					@ -1377,6 +1417,78 @@ int snd_config_save(snd_config_t *config, snd_output_t *out)
 | 
				
			||||||
	return _snd_config_save_leaves(config, out, 0, 0);
 | 
						return _snd_config_save_leaves(config, out, 0, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  *** search macros ***
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SND_CONFIG_SEARCH(config, key, result, extra_code) \
 | 
				
			||||||
 | 
					{ \
 | 
				
			||||||
 | 
						snd_config_t *n; \
 | 
				
			||||||
 | 
						int err; \
 | 
				
			||||||
 | 
						const char *p; \
 | 
				
			||||||
 | 
						assert(config && key); \
 | 
				
			||||||
 | 
						while (1) { \
 | 
				
			||||||
 | 
							if (config->type != SND_CONFIG_TYPE_COMPOUND) \
 | 
				
			||||||
 | 
								return -ENOENT; \
 | 
				
			||||||
 | 
							{ extra_code ; } \
 | 
				
			||||||
 | 
							p = strchr(key, '.'); \
 | 
				
			||||||
 | 
							if (p) { \
 | 
				
			||||||
 | 
								err = _snd_config_search(config, key, p - key, &n); \
 | 
				
			||||||
 | 
								if (err < 0) \
 | 
				
			||||||
 | 
									return err; \
 | 
				
			||||||
 | 
								config = n; \
 | 
				
			||||||
 | 
								key = p + 1; \
 | 
				
			||||||
 | 
							} else \
 | 
				
			||||||
 | 
								return _snd_config_search(config, key, -1, result); \
 | 
				
			||||||
 | 
						} \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SND_CONFIG_SEARCHV(config, result, fcn) \
 | 
				
			||||||
 | 
					{ \
 | 
				
			||||||
 | 
						snd_config_t *n; \
 | 
				
			||||||
 | 
						va_list arg; \
 | 
				
			||||||
 | 
						assert(config); \
 | 
				
			||||||
 | 
						va_start(arg, result); \
 | 
				
			||||||
 | 
						while (1) { \
 | 
				
			||||||
 | 
							const char *k = va_arg(arg, const char *); \
 | 
				
			||||||
 | 
							int err; \
 | 
				
			||||||
 | 
							if (!k) \
 | 
				
			||||||
 | 
								break; \
 | 
				
			||||||
 | 
							err = fcn(config, k, &n); \
 | 
				
			||||||
 | 
							if (err < 0) \
 | 
				
			||||||
 | 
								return err; \
 | 
				
			||||||
 | 
							config = n; \
 | 
				
			||||||
 | 
						} \
 | 
				
			||||||
 | 
						va_end(arg); \
 | 
				
			||||||
 | 
						if (result) \
 | 
				
			||||||
 | 
							*result = n; \
 | 
				
			||||||
 | 
						return 0; \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
 | 
				
			||||||
 | 
					{ \
 | 
				
			||||||
 | 
						snd_config_t *res = NULL; \
 | 
				
			||||||
 | 
						int err, first = 1; \
 | 
				
			||||||
 | 
						assert(config && key); \
 | 
				
			||||||
 | 
						do { \
 | 
				
			||||||
 | 
							err = first && base ? -EIO : fcn1(config, key, &res); \
 | 
				
			||||||
 | 
							if (err < 0) { \
 | 
				
			||||||
 | 
								if (!base) \
 | 
				
			||||||
 | 
									break; \
 | 
				
			||||||
 | 
								err = fcn2(config, &res, base, key, NULL); \
 | 
				
			||||||
 | 
								if (err < 0) \
 | 
				
			||||||
 | 
									break; \
 | 
				
			||||||
 | 
							} \
 | 
				
			||||||
 | 
							first = 0; \
 | 
				
			||||||
 | 
						} while (snd_config_get_string(res, &key) >= 0); \
 | 
				
			||||||
 | 
						if (!res) \
 | 
				
			||||||
 | 
							return err; \
 | 
				
			||||||
 | 
						if (result) \
 | 
				
			||||||
 | 
							*result = res; \
 | 
				
			||||||
 | 
						return 0; \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * \brief Search a node inside a config tree
 | 
					 * \brief Search a node inside a config tree
 | 
				
			||||||
 * \param config Config node handle
 | 
					 * \param config Config node handle
 | 
				
			||||||
| 
						 | 
					@ -1386,23 +1498,7 @@ int snd_config_save(snd_config_t *config, snd_output_t *out)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
 | 
					int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	assert(config && key);
 | 
						SND_CONFIG_SEARCH(config, key, result, );
 | 
				
			||||||
	while (1) {
 | 
					 | 
				
			||||||
		snd_config_t *n;
 | 
					 | 
				
			||||||
		int err;
 | 
					 | 
				
			||||||
		const char *p;
 | 
					 | 
				
			||||||
		if (config->type != SND_CONFIG_TYPE_COMPOUND)
 | 
					 | 
				
			||||||
			return -ENOENT;
 | 
					 | 
				
			||||||
		p = strchr(key, '.');
 | 
					 | 
				
			||||||
		if (p) {
 | 
					 | 
				
			||||||
			err = _snd_config_search(config, key, p - key, &n);
 | 
					 | 
				
			||||||
			if (err < 0)
 | 
					 | 
				
			||||||
				return err;
 | 
					 | 
				
			||||||
			config = n;
 | 
					 | 
				
			||||||
			key = p + 1;
 | 
					 | 
				
			||||||
		} else
 | 
					 | 
				
			||||||
			return _snd_config_search(config, key, -1, result);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -1412,27 +1508,9 @@ int snd_config_search(snd_config_t *config, const char *key, snd_config_t **resu
 | 
				
			||||||
 * \param ... one or more concatenated dot separated search key
 | 
					 * \param ... one or more concatenated dot separated search key
 | 
				
			||||||
 * \return 0 on success otherwise a negative error code
 | 
					 * \return 0 on success otherwise a negative error code
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int snd_config_searchv(snd_config_t *config,
 | 
					int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...)
 | 
				
			||||||
		       snd_config_t **result, ...)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_config_t *n;
 | 
						SND_CONFIG_SEARCHV(config, result, snd_config_search);
 | 
				
			||||||
	va_list arg;
 | 
					 | 
				
			||||||
	assert(config);
 | 
					 | 
				
			||||||
	va_start(arg, result);
 | 
					 | 
				
			||||||
	while (1) {
 | 
					 | 
				
			||||||
		const char *k = va_arg(arg, const char *);
 | 
					 | 
				
			||||||
		int err;
 | 
					 | 
				
			||||||
		if (!k)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		err = snd_config_search(config, k, &n);
 | 
					 | 
				
			||||||
		if (err < 0)
 | 
					 | 
				
			||||||
			return err;
 | 
					 | 
				
			||||||
		config = n;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	va_end(arg);
 | 
					 | 
				
			||||||
	if (result)
 | 
					 | 
				
			||||||
		*result = n;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -1451,24 +1529,59 @@ int snd_config_search_alias(snd_config_t *config,
 | 
				
			||||||
			    const char *base, const char *key,
 | 
								    const char *base, const char *key,
 | 
				
			||||||
			    snd_config_t **result)
 | 
								    snd_config_t **result)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_config_t *res = NULL;
 | 
						SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
 | 
				
			||||||
	int err;
 | 
									snd_config_search, snd_config_searchv);
 | 
				
			||||||
	assert(config && key);
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		err = snd_config_search(config, key, &res);
 | 
					 | 
				
			||||||
		if (err < 0) {
 | 
					 | 
				
			||||||
			if (!base)
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			err = snd_config_searchv(config, &res, base, key, NULL);
 | 
					 | 
				
			||||||
			if (err < 0)
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
	} while (snd_config_get_string(res, &key) >= 0);
 | 
					
 | 
				
			||||||
	if (!res)
 | 
					/**
 | 
				
			||||||
		return err;
 | 
					 * \brief Search a node inside a config tree and expand hooks
 | 
				
			||||||
	if (result)
 | 
					 * \param config Config node handle
 | 
				
			||||||
		*result = res;
 | 
					 * \param key Dot separated search key
 | 
				
			||||||
	return 0;
 | 
					 * \param result Pointer to found node
 | 
				
			||||||
 | 
					 * \return 0 on success otherwise a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static int snd_config_hooks(snd_config_t *config);
 | 
				
			||||||
 | 
						SND_CONFIG_SEARCH(config, key, result, \
 | 
				
			||||||
 | 
										err = snd_config_hooks(config); \
 | 
				
			||||||
 | 
										if (err < 0) \
 | 
				
			||||||
 | 
											return err; \
 | 
				
			||||||
 | 
								 );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Search a node inside a config tree and expand hooks
 | 
				
			||||||
 | 
					 * \param config Config node handle
 | 
				
			||||||
 | 
					 * \param result Pointer to found node
 | 
				
			||||||
 | 
					 * \param ... one or more concatenated dot separated search keyqq
 | 
				
			||||||
 | 
					 * \return 0 on success otherwise a negative error code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int snd_config_searchv_hooks(snd_config_t *config,
 | 
				
			||||||
 | 
								     snd_config_t **result, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						SND_CONFIG_SEARCHV(config, result, snd_config_search_hooks);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Search a node inside a config tree using alias and expand hooks
 | 
				
			||||||
 | 
					 * \param config Config node handle
 | 
				
			||||||
 | 
					 * \param base Key base (or NULL)
 | 
				
			||||||
 | 
					 * \param key Key suffix
 | 
				
			||||||
 | 
					 * \param result Pointer to found node
 | 
				
			||||||
 | 
					 * \return 0 on success otherwise a negative error code
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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_hooks(snd_config_t *config,
 | 
				
			||||||
 | 
									  const char *base, const char *key,
 | 
				
			||||||
 | 
									  snd_config_t **result)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
 | 
				
			||||||
 | 
									snd_config_search_hooks,
 | 
				
			||||||
 | 
									snd_config_searchv_hooks);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Environment variable containing files list for #snd_config_update */
 | 
					/** Environment variable containing files list for #snd_config_update */
 | 
				
			||||||
| 
						 | 
					@ -1486,21 +1599,158 @@ static struct finfo {
 | 
				
			||||||
	dev_t dev;
 | 
						dev_t dev;
 | 
				
			||||||
	ino_t ino;
 | 
						ino_t ino;
 | 
				
			||||||
	time_t mtime;
 | 
						time_t mtime;
 | 
				
			||||||
} *files_info = NULL, *preloaded_files_info = NULL;
 | 
					} *files_info = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned int files_info_count = 0, preloaded_files_info_count = 0;
 | 
					static unsigned int files_info_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int snd_config_preload(snd_config_t *root)
 | 
					static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *h = NULL;
 | 
				
			||||||
 | 
						snd_config_t *c, *func_conf = NULL;
 | 
				
			||||||
 | 
						char *buf = NULL;
 | 
				
			||||||
 | 
						const char *lib = NULL, *func_name = NULL;
 | 
				
			||||||
 | 
						const char *str;
 | 
				
			||||||
 | 
						int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst) = NULL;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = snd_config_search(config, "func", &c);
 | 
				
			||||||
 | 
						if (err < 0) {
 | 
				
			||||||
 | 
							SNDERR("Field func is missing");
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = snd_config_get_string(c, &str);
 | 
				
			||||||
 | 
						if (err < 0) {
 | 
				
			||||||
 | 
							SNDERR("Invalid type for field func");
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = snd_config_search_definition(root, "hook_func", str, &func_conf);
 | 
				
			||||||
 | 
						if (err >= 0) {
 | 
				
			||||||
 | 
							snd_config_iterator_t i, next;
 | 
				
			||||||
 | 
							if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
 | 
				
			||||||
 | 
								SNDERR("Invalid type for func %s definition", str);
 | 
				
			||||||
 | 
								goto _err;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							snd_config_for_each(i, next, func_conf) {
 | 
				
			||||||
 | 
								snd_config_t *n = snd_config_iterator_entry(i);
 | 
				
			||||||
 | 
								const char *id = snd_config_get_id(n);
 | 
				
			||||||
 | 
								if (strcmp(id, "comment") == 0)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								if (strcmp(id, "lib") == 0) {
 | 
				
			||||||
 | 
									err = snd_config_get_string(n, &lib);
 | 
				
			||||||
 | 
									if (err < 0) {
 | 
				
			||||||
 | 
										SNDERR("Invalid type for %s", id);
 | 
				
			||||||
 | 
										goto _err;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (strcmp(id, "func") == 0) {
 | 
				
			||||||
 | 
									err = snd_config_get_string(n, &func_name);
 | 
				
			||||||
 | 
									if (err < 0) {
 | 
				
			||||||
 | 
										SNDERR("Invalid type for %s", id);
 | 
				
			||||||
 | 
										goto _err;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								SNDERR("Unknown field %s", id);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!func_name) {
 | 
				
			||||||
 | 
							int len = 16 + strlen(str) + 1;
 | 
				
			||||||
 | 
							buf = malloc(len);
 | 
				
			||||||
 | 
							snprintf(buf, len, "snd_config_hook_%s", str);
 | 
				
			||||||
 | 
							buf[len-1] = '\0';
 | 
				
			||||||
 | 
							func_name = buf;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!lib)
 | 
				
			||||||
 | 
							lib = ALSA_LIB;
 | 
				
			||||||
 | 
						h = dlopen(lib, RTLD_NOW);
 | 
				
			||||||
 | 
						func = h ? dlsym(h, func_name) : NULL;
 | 
				
			||||||
 | 
						err = 0;
 | 
				
			||||||
 | 
						if (!h) {
 | 
				
			||||||
 | 
							SNDERR("Cannot open shared library %s", lib);
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
						} else if (!func) {
 | 
				
			||||||
 | 
							SNDERR("symbol %s is not defined inside %s", func_name, lib);
 | 
				
			||||||
 | 
							dlclose(h);
 | 
				
			||||||
 | 
							return -ENXIO;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_err:
 | 
				
			||||||
 | 
						if (func_conf)
 | 
				
			||||||
 | 
							snd_config_delete(func_conf);
 | 
				
			||||||
 | 
						if (err >= 0) {
 | 
				
			||||||
 | 
							snd_config_t *nroot;
 | 
				
			||||||
 | 
							err = func(root, config, &nroot);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
 | 
				
			||||||
 | 
							dlclose(h);
 | 
				
			||||||
 | 
							if (err >= 0 && nroot)
 | 
				
			||||||
 | 
								snd_config_substitute(root, nroot);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (buf)
 | 
				
			||||||
 | 
							free(buf);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int snd_config_hooks(snd_config_t *config)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_config_t *n;
 | 
						snd_config_t *n;
 | 
				
			||||||
	snd_config_iterator_t i, next;
 | 
						snd_config_iterator_t i, next;
 | 
				
			||||||
	struct finfo *fi = NULL;
 | 
						int err, hit, idx = 0;
 | 
				
			||||||
	int err, idx = 0, fi_idx = 0, fi_count = 0, hit;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((err = snd_config_search(root, "preload", &n)) < 0)
 | 
						if ((err = snd_config_search(config, "@hooks", &n)) < 0)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	if ((err = snd_config_search(n, "filenames", &n)) < 0) {
 | 
						snd_config_remove(n);
 | 
				
			||||||
		SNDERR("Unable to find filenames in the preload section");
 | 
						do {
 | 
				
			||||||
 | 
							hit = 0;
 | 
				
			||||||
 | 
							snd_config_for_each(i, next, n) {
 | 
				
			||||||
 | 
								snd_config_t *n = snd_config_iterator_entry(i);
 | 
				
			||||||
 | 
								const char *id = snd_config_get_id(n);
 | 
				
			||||||
 | 
								long i;
 | 
				
			||||||
 | 
								err = safe_strtol(id, &i);
 | 
				
			||||||
 | 
								if (err < 0) {
 | 
				
			||||||
 | 
									SNDERR("id of field %s is not and integer", id);
 | 
				
			||||||
 | 
									err = -EINVAL;
 | 
				
			||||||
 | 
									goto _err;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (i == idx) {
 | 
				
			||||||
 | 
									err = snd_config_hooks_call(config, n);
 | 
				
			||||||
 | 
									if (err < 0)
 | 
				
			||||||
 | 
										return err;
 | 
				
			||||||
 | 
									idx++;
 | 
				
			||||||
 | 
									hit = 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} while (hit);
 | 
				
			||||||
 | 
						err = 0;
 | 
				
			||||||
 | 
					       _err:
 | 
				
			||||||
 | 
						snd_config_delete(n);
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						snd_config_t *n, *res = NULL;
 | 
				
			||||||
 | 
						snd_config_iterator_t i, next;
 | 
				
			||||||
 | 
						struct finfo *fi = NULL;
 | 
				
			||||||
 | 
						int err, idx = 0, fi_count = 0, errors = 1, hit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(root && dst);
 | 
				
			||||||
 | 
						if ((err = snd_config_search(config, "errors", &n)) >= 0) {
 | 
				
			||||||
 | 
							char *tmp;
 | 
				
			||||||
 | 
							err = snd_config_get_ascii(n, &tmp);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
							errors = snd_config_get_bool_ascii(tmp);
 | 
				
			||||||
 | 
							free(tmp);
 | 
				
			||||||
 | 
							if (errors < 0) {
 | 
				
			||||||
 | 
								SNDERR("Invalid bool value in field errors");
 | 
				
			||||||
 | 
								return errors;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ((err = snd_config_search(config, "files", &n)) < 0) {
 | 
				
			||||||
 | 
							SNDERR("Unable to find field files in the preload section");
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if ((err = snd_config_expand(n, root, NULL, NULL, &n)) < 0) {
 | 
						if ((err = snd_config_expand(n, root, NULL, NULL, &n)) < 0) {
 | 
				
			||||||
| 
						 | 
					@ -1539,7 +1789,6 @@ static int snd_config_preload(snd_config_t *root)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (i == idx) {
 | 
								if (i == idx) {
 | 
				
			||||||
				wordexp_t we;
 | 
									wordexp_t we;
 | 
				
			||||||
				struct stat st;
 | 
					 | 
				
			||||||
				char *name;
 | 
									char *name;
 | 
				
			||||||
				if ((err = snd_config_get_ascii(n, &name)) < 0)
 | 
									if ((err = snd_config_get_ascii(n, &name)) < 0)
 | 
				
			||||||
					goto _err;
 | 
										goto _err;
 | 
				
			||||||
| 
						 | 
					@ -1556,51 +1805,48 @@ static int snd_config_preload(snd_config_t *root)
 | 
				
			||||||
					err = -EINVAL;
 | 
										err = -EINVAL;
 | 
				
			||||||
					goto _err;
 | 
										goto _err;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				fi[fi_idx].name = strdup(we.we_wordv[0]);
 | 
									fi[idx].name = strdup(we.we_wordv[0]);
 | 
				
			||||||
				wordfree(&we);
 | 
									wordfree(&we);
 | 
				
			||||||
				free(name);
 | 
									free(name);
 | 
				
			||||||
				if (fi[fi_idx].name == NULL) {
 | 
									if (fi[idx].name == NULL) {
 | 
				
			||||||
					err = -ENOMEM;
 | 
										err = -ENOMEM;
 | 
				
			||||||
					goto _err;
 | 
										goto _err;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (stat(fi[fi_idx].name, &st) < 0) {
 | 
					 | 
				
			||||||
					free(fi[fi_idx].name);
 | 
					 | 
				
			||||||
					fi[fi_idx].name = NULL;
 | 
					 | 
				
			||||||
					fi_count--;
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					fi[fi_idx].dev = st.st_dev;
 | 
					 | 
				
			||||||
					fi[fi_idx].ino = st.st_ino;
 | 
					 | 
				
			||||||
					fi[fi_idx].mtime = st.st_mtime;
 | 
					 | 
				
			||||||
					fi_idx++;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				idx++;
 | 
									idx++;
 | 
				
			||||||
				hit = 1;
 | 
									hit = 1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} while (hit);
 | 
						} while (hit);
 | 
				
			||||||
	for (fi_idx = 0; fi_idx < fi_count; fi_idx++) {
 | 
						err = snd_config_top(&res);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							goto _err;
 | 
				
			||||||
 | 
						for (idx = 0; idx < fi_count; idx++) {
 | 
				
			||||||
		snd_input_t *in;
 | 
							snd_input_t *in;
 | 
				
			||||||
		err = snd_input_stdio_open(&in, fi[fi_idx].name, "r");
 | 
							if (!errors && access(fi[idx].name, R_OK) < 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							err = snd_input_stdio_open(&in, fi[idx].name, "r");
 | 
				
			||||||
		if (err >= 0) {
 | 
							if (err >= 0) {
 | 
				
			||||||
			err = snd_config_load(snd_config, in);
 | 
								err = snd_config_load(root, in);
 | 
				
			||||||
			snd_input_close(in);
 | 
								snd_input_close(in);
 | 
				
			||||||
			if (err < 0) {
 | 
								if (err < 0) {
 | 
				
			||||||
				SNDERR("%s may be old or corrupted: consider to remove or fix it", fi[fi_idx].name);
 | 
									SNDERR("%s may be old or corrupted: consider to remove or fix it", fi[idx].name);
 | 
				
			||||||
				goto _err;
 | 
									goto _err;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			SNDERR("cannot access file %s", fi[fi_idx].name);
 | 
								SNDERR("cannot access file %s", fi[idx].name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	preloaded_files_info = fi; fi = NULL;
 | 
						*dst = NULL;
 | 
				
			||||||
	preloaded_files_info_count = fi_count; fi_count = 0;
 | 
						res = NULL;
 | 
				
			||||||
	err = 0;
 | 
						err = 0;
 | 
				
			||||||
       _err:
 | 
					       _err:
 | 
				
			||||||
       	for (fi_idx = 0; fi_idx < fi_count; fi_idx++)
 | 
						for (idx = 0; idx < fi_count; idx++)
 | 
				
			||||||
       		if (fi[fi_idx].name)
 | 
					       		if (fi[idx].name)
 | 
				
			||||||
       			free(fi[fi_idx].name);
 | 
					       			free(fi[idx].name);
 | 
				
			||||||
       	if (fi)
 | 
					       	if (fi)
 | 
				
			||||||
       		free(fi);
 | 
					       		free(fi);
 | 
				
			||||||
 | 
					       	if (res)
 | 
				
			||||||
 | 
					       		snd_config_delete(res);
 | 
				
			||||||
	snd_config_delete(n);
 | 
						snd_config_delete(n);
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1691,15 +1937,6 @@ int snd_config_update()
 | 
				
			||||||
		    fi[k].mtime != files_info[k].mtime)
 | 
							    fi[k].mtime != files_info[k].mtime)
 | 
				
			||||||
			goto _reread;
 | 
								goto _reread;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for (k = 0; k < preloaded_files_info_count; k++) {
 | 
					 | 
				
			||||||
		struct stat st;
 | 
					 | 
				
			||||||
		if (stat(preloaded_files_info[k].name, &st) >= 0) {
 | 
					 | 
				
			||||||
			if (preloaded_files_info[k].dev != st.st_dev ||
 | 
					 | 
				
			||||||
			    preloaded_files_info[k].ino != st.st_ino ||
 | 
					 | 
				
			||||||
			    preloaded_files_info[k].mtime != st.st_mtime)
 | 
					 | 
				
			||||||
				goto _reread;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	err = 0;
 | 
						err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 _end:
 | 
					 _end:
 | 
				
			||||||
| 
						 | 
					@ -1721,13 +1958,6 @@ int snd_config_update()
 | 
				
			||||||
		files_info = NULL;
 | 
							files_info = NULL;
 | 
				
			||||||
		files_info_count = 0;
 | 
							files_info_count = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (preloaded_files_info) {
 | 
					 | 
				
			||||||
		for (k = 0; k < preloaded_files_info_count; ++k)
 | 
					 | 
				
			||||||
			free(preloaded_files_info[k].name);
 | 
					 | 
				
			||||||
		free(preloaded_files_info);
 | 
					 | 
				
			||||||
		preloaded_files_info = NULL;
 | 
					 | 
				
			||||||
		preloaded_files_info_count = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (snd_config) {
 | 
						if (snd_config) {
 | 
				
			||||||
		snd_config_delete(snd_config);
 | 
							snd_config_delete(snd_config);
 | 
				
			||||||
		snd_config = NULL;
 | 
							snd_config = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1749,9 +1979,9 @@ int snd_config_update()
 | 
				
			||||||
			SNDERR("cannot access file %s", fi[k].name);
 | 
								SNDERR("cannot access file %s", fi[k].name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = snd_config_preload(snd_config);
 | 
						err = snd_config_hooks(snd_config);
 | 
				
			||||||
	if (err < 0) {
 | 
						if (err < 0) {
 | 
				
			||||||
		SNDERR("preload failed, removing configuration");
 | 
							SNDERR("hooks failed, removing configuration");
 | 
				
			||||||
		goto _end;
 | 
							goto _end;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	files_info = fi;
 | 
						files_info = fi;
 | 
				
			||||||
| 
						 | 
					@ -2008,23 +2238,6 @@ static int _snd_config_expand(snd_config_t *src,
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void snd_config_substitute(snd_config_t *dst, snd_config_t *src)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (src->type == SND_CONFIG_TYPE_COMPOUND) {
 | 
					 | 
				
			||||||
		snd_config_iterator_t i, next;
 | 
					 | 
				
			||||||
		snd_config_for_each(i, next, src) {
 | 
					 | 
				
			||||||
			snd_config_t *n = snd_config_iterator_entry(i);
 | 
					 | 
				
			||||||
			n->father = dst;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		src->u.compound.fields.next->prev = &dst->u.compound.fields;
 | 
					 | 
				
			||||||
		src->u.compound.fields.prev->next = &dst->u.compound.fields;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	free(dst->id);
 | 
					 | 
				
			||||||
	dst->id  = src->id;
 | 
					 | 
				
			||||||
	dst->type = src->type;
 | 
					 | 
				
			||||||
	dst->u = src->u;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int _snd_config_evaluate(snd_config_t *src,
 | 
					static int _snd_config_evaluate(snd_config_t *src,
 | 
				
			||||||
				snd_config_t *root,
 | 
									snd_config_t *root,
 | 
				
			||||||
				snd_config_t **dst ATTRIBUTE_UNUSED,
 | 
									snd_config_t **dst ATTRIBUTE_UNUSED,
 | 
				
			||||||
| 
						 | 
					@ -2068,7 +2281,7 @@ static int _snd_config_evaluate(snd_config_t *src,
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (strcmp(id, "open") == 0) {
 | 
									if (strcmp(id, "func") == 0) {
 | 
				
			||||||
					err = snd_config_get_string(n, &func_name);
 | 
										err = snd_config_get_string(n, &func_name);
 | 
				
			||||||
					if (err < 0) {
 | 
										if (err < 0) {
 | 
				
			||||||
						SNDERR("Invalid type for %s", id);
 | 
											SNDERR("Invalid type for %s", id);
 | 
				
			||||||
| 
						 | 
					@ -2108,10 +2321,8 @@ static int _snd_config_evaluate(snd_config_t *src,
 | 
				
			||||||
			if (err < 0)
 | 
								if (err < 0)
 | 
				
			||||||
				SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
 | 
									SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
 | 
				
			||||||
			dlclose(h);
 | 
								dlclose(h);
 | 
				
			||||||
			if (err >= 0 && eval) {
 | 
								if (err >= 0 && eval)
 | 
				
			||||||
				snd_config_substitute(src, eval);
 | 
									snd_config_substitute(src, eval);
 | 
				
			||||||
				free(eval);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (buf)
 | 
							if (buf)
 | 
				
			||||||
			free(buf);
 | 
								free(buf);
 | 
				
			||||||
| 
						 | 
					@ -2559,7 +2770,7 @@ int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * \brief Search a node inside a config tree using alias
 | 
					 * \brief Search a definition inside a config tree using alias and expand hooks and arguments
 | 
				
			||||||
 * \param config Config node handle
 | 
					 * \param config Config node handle
 | 
				
			||||||
 * \param base Key base (or NULL)
 | 
					 * \param base Key base (or NULL)
 | 
				
			||||||
 * \param key Key suffix
 | 
					 * \param key Key suffix
 | 
				
			||||||
| 
						 | 
					@ -2586,7 +2797,7 @@ int snd_config_search_definition(snd_config_t *config,
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		key = (char *) name;
 | 
							key = (char *) name;
 | 
				
			||||||
	} 
 | 
						} 
 | 
				
			||||||
	err = snd_config_search_alias(config, base, key, &conf);
 | 
						err = snd_config_search_alias_hooks(config, base, key, &conf);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
	return snd_config_expand(conf, config, args, NULL, result);
 | 
						return snd_config_expand(conf, config, args, NULL, result);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -691,7 +691,3 @@ int snd_func_refer(snd_config_t **dst, snd_config_t *root, snd_config_t *src, vo
 | 
				
			||||||
 _end:
 | 
					 _end:
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
int snd_func_macro(snd_config_t **dst, snd_config_t *root,
 | 
					 | 
				
			||||||
		   snd_config_t *src, void *private_data)
 | 
					 | 
				
			||||||
		   	__attribute__ ((weak, alias ("snd_func_refer")));
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue