参照元

説明

引数

返り値

参考

実装

static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
			     snd_config_t *pcm_root, snd_config_t *pcm_conf,
			     snd_pcm_stream_t stream, int mode)
{
	const char *str;
	char *buf = NULL, *buf1 = NULL;
	int err;
	snd_config_t *conf, *type_conf = NULL, *tmp;
	snd_config_iterator_t i, next;
	const char *id;
	const char *lib = NULL, *open_name = NULL;
	int (*open_func)(snd_pcm_t **, const char *, 
			 snd_config_t *, snd_config_t *, 
			 snd_pcm_stream_t, int) = NULL;
#ifndef PIC
	extern void *snd_pcm_open_symbols(void);
#endif
	if (snd_config_get_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) {
		char *val;
		id = NULL;
		snd_config_get_id(pcm_conf, &id);
		val = NULL;
		snd_config_get_ascii(pcm_conf, &val);
		SNDERR("Invalid type for PCM %s%sdefinition (id: %s, value: %s)", name ? name : "", name ? " " : "", id, val);
		free(val);
		return -EINVAL;
	}
	err = snd_config_search(pcm_conf, "type", &conf);
	if (err < 0) {
		SNDERR("type is not defined");
		return err;
	}
	err = snd_config_get_id(conf, &id);
	if (err < 0) {
		SNDERR("unable to get id");
		return err;
	}
	err = snd_config_get_string(conf, &str);
	if (err < 0) {
		SNDERR("Invalid type for %s", id);
		return err;
	}
	err = snd_config_search_definition(pcm_root, "pcm_type", str, &type_conf);
	if (err >= 0) {
		if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
			SNDERR("Invalid type for PCM type %s definition", str);
			goto _err;
		}
		snd_config_for_each(i, next, type_conf) {
			snd_config_t *n = snd_config_iterator_entry(i);
			const char *id;
			if (snd_config_get_id(n, &id) < 0)
				continue;
			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, "open") == 0) {
				err = snd_config_get_string(n, &open_name);
				if (err < 0) {
					SNDERR("Invalid type for %s", id);
					goto _err;
				}
				continue;
			}
			SNDERR("Unknown field %s", id);
			err = -EINVAL;
			goto _err;
		}
	}
	if (!open_name) {
		buf = malloc(strlen(str) + 32);
		if (buf == NULL) {
			err = -ENOMEM;
			goto _err;
		}
		open_name = buf;
		sprintf(buf, "_snd_pcm_%s_open", str);
	}
	if (!lib) {
		const char *const *build_in = build_in_pcms;
		while (*build_in) {
			if (!strcmp(*build_in, str))
				break;
			build_in++;
		}
		if (*build_in == NULL) {
			buf1 = malloc(strlen(str) + sizeof(ALSA_PLUGIN_DIR) + 32);
			if (buf1 == NULL) {
				err = -ENOMEM;
				goto _err;
			}
			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,
			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) {
			if ((*pcmp)->open_func) {
				/* only init plugin (like empty, asym) */
				snd_dlobj_cache_put(open_func);
			} else {
				(*pcmp)->open_func = open_func;
			}
			err = 0;
		} else {
			snd_dlobj_cache_put(open_func);
		}
	} else {
		err = -ENXIO;
	}
	if (err >= 0) {
		err = snd_config_search(pcm_root, "defaults.pcm.compat", &tmp);
		if (err >= 0) {
			long i;
			if (snd_config_get_integer(tmp, &i) >= 0) {
				if (i > 0)
					(*pcmp)->compat = 1;
			}
		} else {
			char *str = getenv("LIBASOUND_COMPAT");
			if (str && *str)
				(*pcmp)->compat = 1;
		}
		err = snd_config_search(pcm_root, "defaults.pcm.minperiodtime", &tmp);
		if (err >= 0)
			snd_config_get_integer(tmp, &(*pcmp)->minperiodtime);
		err = 0;
	}
       _err:
	if (type_conf)
		snd_config_delete(type_conf);
	free(buf);
	free(buf1);
	return err;
}

コメント


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS