alsa-lib的alsa.conf

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dongkun152/article/details/83030929

alsa-lib的alsa.conf

最近看alsa系统,发现在alsa第一层借口下会有一层配置层,第一层接口通过配置参数调用动态库中指定的函数。这些函数才会去真正操作音频设备节点。
据说alsa.conf功能很强大,现在遇到的问题是,这个中间层对继续梳理alsa上层的调用过程造成了一些麻烦。所以,在这里吧alsa.conf相关的内容整理一哈。

alsa.conf结构和处理过程

alsa.conf主要用来保存一些变量的值。为了完成这个功能,alsa.conf中有三种变量compound(符合类型),string和integer。其中数组也是一种compound,func是作为string出现的,之后在内部进行扩展解释。
alsa.conf最终被解释为一棵树,它的节点是struct _snd_config结构,三种类型的变量都用此结构表示。

struct _snd_config {
	char *id; //节点名
	snd_config_type_t type; //节点类型
	union {
		long integer;
		long long integer64;
		char *string;
		double real;
		const void *ptr;
		struct {
			struct list_head fields;  //作为compound时的子节点链表
			int join;
		} compound;
	} u;
	struct list_head list; //将会链如父节点链表中
	snd_config_t *parent;
	int hop;
};

如下为compound类型外部的赋值语句(在配置文件中第一次出现对该变量的赋值):

defaults.namehint.showall off

赋值语句格式是 var value(变量+space+值)。这里的值是一个字符串。首先构造一个id为defaults,type为compound类型的node(每个node都是struct _snd_config结构),namehint下一个compound节点,并且是defaults的子节点,showall是compound namehint的子节点,它是string类型的,它的值是off。
下面是整数类型的赋值

defaults.ctl.card 0

defaults是刚才构造的compound节点,添加新的ctl compound节点到defaults节点中,card是ctl下的integer类型的节点,它的值为0。
下面这种形式的赋值是一种引用,但是在构造时,就是简单的字符串赋值

defaults.pcm.dmix.card defaults.pcm.card

card是string类型的节点,它的值是字符串defaults.pcm.card. 综上,string和integer类型的节点一定是叶子节点。
运行是构造的节点连接结构如下图
在这里插入图片描述
常见的compound结构如下,在pcm compound节点下,用标准方式构造hw compound节点。

pcm.hw {
	@args [ CARD DEV SUBDEV ]//参数数组,得到@args compound,下面有id为0,值为CARD的string节点等
	@args.CARD { //@args compound节点下有CARD compound节点
		type string
		default {
			@func getenv //特殊字符串节点
			vars [
				ALSA_PCM_CARD
				ALSA_CARD
			]
			default {
				@func refer
				name defaults.pcm.card
			}
		}
	}
	@args.DEV {
		type integer
		default {
			@func igetenv
			vars [
				ALSA_PCM_DEVICE
			]
			default {
				@func refer
				name defaults.pcm.device
			}
		}
	}
	@args.SUBDEV {
		type integer
		default {
			@func refer
			name defaults.pcm.subdevice
		}
	}		
	type hw
	card $CARD  //字符串节点,它的值引用参数CARD
	device $DEV
	subdevice $SUBDEV
	hint {
		show {
			@func refer
			name defaults.namehint.extended
		}
		description "Direct hardware device without any conversions"
	}
}

pcm.hw节点在运行过程中会被展开,最终得到展开后的节点。

hw {
    type hw
	card card_val
	device dev_val
	subdevice subdev_val
	hint {
		show show_val
		description "Direct hardware device without any conversions"
	}
}

card_val, dev_val和subdev_val根据@args获得,show_val由函数展开获得。
函数展开时如下

default {
				@func refer
				name defaults.pcm.card
			}
展开时会调用snd_func_refer函数,根据name的值deaults.pcm.card,搜索全局获得对应的实际值返回作为default的值default_val.
变为
default {
			@func getenv 
			vars [
				ALSA_PCM_CARD
				ALSA_CARD
			]
			default default_val
		}
接下来调用snd_func_getenv函数,使用getenv获取vars中所列的两个环境变量,若都为空,则返回default的值作为最外层的default_val. 若有一个不为空,则返回值做为最外层的default_val.
此时根据@args的信息生成新的节点subs
subs {
CARD {
	type string
	default default_val
}
DEV {
	type integer
	default default_val
}
SUBDEV {
	type integer
	default default_val
}
}

根据展开得到的新节点信息,hw就被展开为最后的形式。
继续添加中。。。。。。。。。。

猜你喜欢

转载自blog.csdn.net/dongkun152/article/details/83030929