diff --git a/src/control/control.c b/src/control/control.c index d66ed75..42cecad 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -838,6 +838,10 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, #ifndef PIC extern void *snd_control_open_symbols(void); #endif + + snd_config_t *libs = NULL; + const char *libs_lib = NULL; + if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND) { if (name) SNDERR("Invalid type for CTL %s definition", name); @@ -879,6 +883,19 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, SNDERR("Invalid type for %s", id); goto _err; } + + continue; + } + // Handle an array of extra libs. + if (strcmp(id, "libs") == 0) { + if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { + SNDERR("Invalid type for libs definition in CTL %s definition", + str); + goto _err; + } + + libs = n; + continue; } if (strcmp(id, "open") == 0) { @@ -903,7 +920,62 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, open_name = buf; sprintf(buf, "_snd_ctl_%s_open", str); } - if (!lib) { + +#ifndef PIC + snd_control_open_symbols(); +#endif + + // Normal alsa behaviour when there is no libs array. + if (!libs) { + if (lib) { + open_func = snd_dlobj_cache_get(lib, open_name, + SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION), 1); + } + } + // Handle libs array. + // Suppresses error messages if any function is loaded successfully. + else { + if (lib) { + open_func = snd_dlobj_cache_get(lib, open_name, + SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION), 0); + } + + if (!open_func) { + snd_config_for_each(i, next, libs) { + snd_config_t *n = snd_config_iterator_entry(i); + + err = snd_config_get_string(n, &libs_lib); + if (err < 0) { + SNDERR("Invalid entry in CTL %s libs definition", str); + goto _err; + } + + if (!open_func) { + open_func = snd_dlobj_cache_get(libs_lib, open_name, + SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION), 0); + } + } + } + + // Print error messages. + if (!open_func) { + if (lib) { + SNDERR("Either %s cannot be opened or %s was not defined inside", + lib, open_name); + } + + snd_config_for_each(i, next, libs) { + snd_config_t *n = snd_config_iterator_entry(i); + + snd_config_get_string(n, &libs_lib); + SNDERR("Either %s cannot be opened or %s was not defined inside", + libs_lib, open_name); + } + } + } + + // Look in ALSA_PLUGIN_DIR iff we found nowhere else to look. + if (!lib && (!libs || !libs_lib)) { const char *const *build_in = build_in_ctls; while (*build_in) { if (!strcmp(*build_in, str)) @@ -919,12 +991,11 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, lib = buf1; sprintf(buf1, "%s/libasound_module_ctl_%s.so", ALSA_PLUGIN_DIR, str); } - } -#ifndef PIC - snd_control_open_symbols(); -#endif - open_func = snd_dlobj_cache_get(lib, open_name, + + open_func = snd_dlobj_cache_get(lib, open_name, SND_DLSYM_VERSION(SND_CONTROL_DLSYM_VERSION), 1); + } + if (open_func) { err = open_func(ctlp, name, ctl_root, ctl_conf, mode); if (err >= 0) { diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 2e24338..7f489f4 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -2116,6 +2116,10 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, #ifndef PIC extern void *snd_pcm_open_symbols(void); #endif + + snd_config_t *libs = NULL; + const char *libs_lib = NULL; + if (snd_config_get_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) { char *val; id = NULL; @@ -2160,6 +2164,19 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, SNDERR("Invalid type for %s", id); goto _err; } + + continue; + } + // Handle an array of extra libs. + if (strcmp(id, "libs") == 0) { + if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { + SNDERR("Invalid type for libs definition in PCM %s definition", + str); + goto _err; + } + + libs = n; + continue; } if (strcmp(id, "open") == 0) { @@ -2184,7 +2201,62 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, open_name = buf; sprintf(buf, "_snd_pcm_%s_open", str); } - if (!lib) { + +#ifndef PIC + snd_pcm_open_symbols(); /* this call is for static linking only */ +#endif + + // Normal alsa behaviour when there is no libs array. + if (!libs) { + if (lib) { + open_func = snd_dlobj_cache_get(lib, open_name, + SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 1); + } + } + // Handle libs array. + // Suppresses error messages if any function is loaded successfully. + else { + if (lib) { + open_func = snd_dlobj_cache_get(lib, open_name, + SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 0); + } + + if (!open_func) { + snd_config_for_each(i, next, libs) { + snd_config_t *n = snd_config_iterator_entry(i); + + err = snd_config_get_string(n, &libs_lib); + if (err < 0) { + SNDERR("Invalid entry in PCM %s libs definition", str); + goto _err; + } + + if (!open_func) { + open_func = snd_dlobj_cache_get(libs_lib, open_name, + SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 0); + } + } + } + + // Print error messages. + if (!open_func) { + if (lib) { + SNDERR("Either %s cannot be opened or %s was not defined inside", + lib, open_name); + } + + snd_config_for_each(i, next, libs) { + snd_config_t *n = snd_config_iterator_entry(i); + + snd_config_get_string(n, &libs_lib); + SNDERR("Either %s cannot be opened or %s was not defined inside", + libs_lib, open_name); + } + } + } + + // Look in ALSA_PLUGIN_DIR iff we found nowhere else to look. + if (!lib && (!libs || !libs_lib)) { const char *const *build_in = build_in_pcms; while (*build_in) { if (!strcmp(*build_in, str)) @@ -2200,12 +2272,11 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, lib = buf1; sprintf(buf1, "%s/libasound_module_pcm_%s.so", ALSA_PLUGIN_DIR, str); } - } -#ifndef PIC - snd_pcm_open_symbols(); /* this call is for static linking only */ -#endif - open_func = snd_dlobj_cache_get(lib, open_name, + + open_func = snd_dlobj_cache_get(lib, open_name, SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 1); + } + if (open_func) { err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode); if (err >= 0) {