ALSA 用例配置。參考 ALSA 用例配置 來了解更詳細(xì)信息。
ALSA 用例配置
用例配置文件使用 配置文件 語法來定義靜態(tài)配置樹。該樹在運(yùn)行時(shí)根據(jù)配置樹中的條件和動(dòng)態(tài)變量進(jìn)行評(píng)估(修改)。使用 用例接口 API 解析結(jié)果并將其導(dǎo)出到應(yīng)用程序。
配置目錄和主文件名查找
查找路徑在 ucm.conf 文件中描述。配置結(jié)構(gòu)看起來像下面這樣:
UseCasePath.path1 {
Directory "conf.virt.d"
File "${OpenName}.conf"
}
UseCasePath.path2 {
Directory "external"
File "${OpenName}.conf"
}
現(xiàn)代 Linux 中,ucm.conf 文件通常位于/usr/share/alsa/ucm2/ucm.conf,該文件結(jié)構(gòu)大體如下:
#
# This is the toplevel file included from the alsa-lib.
#
# It allows to add extra lookups for the old kernels or so.
#
# You may specify the directory (relative to the toplevel) and
# the master configuration file which defines the verbs.
#
#
# Syntax version is reset for the master configuration file.
#
Syntax 3
Define.V1 "" # non-empty string to enable ucm v1 paths
Define.V2Module yes # empty string to disable
Define.V2Name yes # empty string to disable
If.driver {
Condition {
Type String
Empty "${CardNumber}"
}
True {
#
# The probed path for no-hw-card:
#
# ucm2/${OpenName}/${OpenName}.conf
#
UseCasePath {
legacy {
Directory "${OpenName}"
File "${OpenName}.conf"
}
}
}
False {
#
# The probed path when hw-card is found:
#
# ucm2/${KernelModule}/${KernelModule}.conf
# ucm2/${CardDriver}/${CardLongName}.conf
# ucm2/${CardDriver}/${CardDriver}.conf
#
If.V2Module {
Condition {
Type String
Empty "${var:V2Module}"
}
False {
Define.KernelModulePath "class/sound/card${CardNumber}/device/driver"
Define.KernelModule "${sys:$KernelModulePath}"
UseCasePath.module {
Directory "module"
File "${var:KernelModule}.conf"
}
}
}
If.V2Name {
Condition {
Type String
Empty "${var:V2Name}"
}
False.UseCasePath {
longname {
Directory "${CardDriver}"
File "${CardLongName}.conf"
}
driver {
Directory "${CardDriver}"
File "${CardDriver}.conf"
}
}
}
}
}
If.V1 {
Condition {
Type String
Empty "${var:V1}"
}
False.If.v1_driver {
Condition {
Type String
Empty "${CardNumber}"
}
True {
#
# The probed path for no-hw-card:
#
# ucm/${OpenName}/${OpenName}.conf
#
UseCasePath.v1_legacy {
Version 1
Directory "${OpenName}"
File "${OpenName}.conf"
}
}
False {
#
# The ucm v1 probed path when hw-card is found:
#
# ucm/${CardLongName}/${CardLongName}.conf
# ucm/${CardName}/${CardName}.conf or \
# ucm/${OpenName}/${OpenName}.conf
#
UseCasePath.v1_longname {
Version 1
Directory "${CardLongName}"
File "${CardLongName}.conf"
}
If.v1_hw {
Condition {
Type String
Haystack "${OpenName}"
Needle "hw:"
}
True.UseCasePath.v1_cardnamme {
Version 1
Directory "${CardName}"
File "${CardName}.conf"
}
False.UseCasePath.v1_openname {
Version 1
Directory "${OpenName}"
File "${OpenName}.conf"
}
}
}
}
}
UCM 主配置文件
每個(gè)聲卡都有一個(gè)主聲卡文件,它列出聲卡支持的所有用例 verbs,如:
# Example master file for blah sound card
# By Joe Blogs <joe@bloggs.org>
Syntax 6
# Use Case name for user interface
Comment "Nice Abstracted Soundcard"
# The file is divided into Use case sections. One section per use case verb.
SectionUseCase."Voice Call" {
File "voice_call_blah"
Comment "Make a voice phone call."
}
SectionUseCase."HiFi" {
File "hifi_blah"
Comment "Play and record HiFi quality Music."
}
# Define Value defaults
ValueDefaults {
PlaybackChannels 4
CaptureChannels 4
}
# Define boot / initialization sequence
# This sequence is skipped, when the soundcard was already configured by system
# (alsactl configuration was already created). The purpose is to not alter
# ALSA card controls which may be modified by user after initial settings.
BootSequence [
cset "name='Master Playback Switch',index=2 0,0"
cset "name='Master Playback Volume',index=2 25,25"
msleep 50
cset "name='Master Playback Switch',index=2 1,1"
cset "name='Master Playback Volume',index=2 50,50"
]
# Define fixed boot sequence
# This sequence is always executed on boot (hotplug).
FixedBootSequence [
cset "name='Something to toggle' toggle"
]
UCM verb 配置文件
verb 配置文件定義設(shè)備,修飾符和初始化序列。它有點(diǎn)像聲音配置文件。
# Example Use case verb section for Voice call blah
# By Joe Blogs <joe@blogs.com>
# verb global section
SectionVerb {
# enable and disable sequences are compulsory
EnableSequence [
disdevall "" # run DisableSequence for all devices
]
DisableSequence [
cset "name='Power Save' on"
]
# Optional transition verb
TransitionSequence."ToCaseName" [
disdevall "" # run DisableSequence for all devices
msleep 1
]
# Optional TQ and device values
Value {
TQ HiFi
PlaybackChannels 6
}
}
# Each device is described in new section. N devices are allowed
SectionDevice."Headphones" {
SupportedDevice [
"x"
"y"
]
# or (not both)
ConflictingDevice [
"x"
"y"
]
EnableSequence [
...
]
DisableSequence [
...
]
TransitionSequence."ToDevice" [
...
]
Value {
PlaybackVolume "name='Master Playback Volume',index=2"
PlaybackSwitch "name='Master Playback Switch',index=2"
PlaybackPCM "hw:${CardId},4"
}
}
# Each modifier is described in new section. N modifiers are allowed
SectionModifier."Capture Voice" {
Comment "Record voice call"
SupportedDevice [
"x"
"y"
]
# or (not both)
ConflictingDevice [
"x"
"y"
]
EnableSequence [
...
]
DisableSequence [
...
]
TransitionSequence."ToModifierName" [
...
]
# Optional TQ and ALSA PCMs
Value {
TQ Voice
CapturePCM "hw:${CardId},11"
PlaybackMixerElem "Master"
PlaybackVolume "name='Master Playback Volume',index=2"
PlaybackSwitch "name='Master Playback Switch',index=2"
}
}
序列圖


序列命令
| 命令名稱 | 描述 |
|---|---|
| enadev2 ARG | 執(zhí)行設(shè)備啟用序列 |
| disdev2 ARG | 執(zhí)行設(shè)備禁用序列 |
| disdevall "" | 為 verb 中的所有設(shè)備執(zhí)行設(shè)備禁用序列 |
| cdev ARG | 為 ALSA 控制設(shè)備名調(diào)用 snd_ctl_open() |
| cset ARG | ALSA 控制設(shè)置 - snd_ctl_ascii_elem_id_parse() + snd_ctl_ascii_value_parse() |
| cset-new ARG | 創(chuàng)建新的 ALSA 用戶控制元素 - snd_ctl_ascii_elem_id_parse() + 描述 |
| ctl-remove ARG | 移除 ALSA 用戶控制元素 - snd_ctl_ascii_elem_id_parse() |
| sysw ARG | 寫入 sysfs 樹 |
| usleep ARG | 休眠指定的微妙數(shù) |
| msleep ARG | 休眠指定的毫妙數(shù) |
| exec ARG | 執(zhí)行指定的命令 (不通過 shell - man execv) |
| shell ARG | 執(zhí)行指定的命令 (使用 shell - man system) |
| cfg-save ARG | 將 LibraryConfig 保存到文件 |
# Examples
cset "name='PCM Playback Volue',index=2 99"
cset-new "name='Bool2' type=bool,count=2 1,0"
cset-new "name='Enum' type=enum,labels='L1;L2;L3' 'L2'"
ctl-remove "name='Bool2'"
sysw "-/class/sound/ctl-led/speaker/card${CardNumber}/attach:Speaker Channel Switch"
usleep 10
exec "/bin/echo hello"
shell "set"
cfg-save "/tmp/test.conf:+pcm"
這些命令用在用例管理的配置文件里,而不是 alsaucm 命令行工具。
名稱
參考帶有 SND_USE_CASE_VERB 前綴的宏,如 SND_USE_CASE_VERB_HIFI 來了解已知 verb 的完整列表。
#define SND_USE_CASE_VERB_ANALOG_RADIO "FM Analog Radio"
#define SND_USE_CASE_VERB_DIGITAL_RADIO "FM Digital Radio"
#define SND_USE_CASE_VERB_HIFI "HiFi"
#define SND_USE_CASE_VERB_HIFI_LOW_POWER "HiFi Low Power"
#define SND_USE_CASE_VERB_INACTIVE "Inactive"
#define SND_USE_CASE_VERB_IP_VOICECALL "Voice Call IP"
#define SND_USE_CASE_VERB_VOICE "Voice"
#define SND_USE_CASE_VERB_VOICE_LOW_POWER "Voice Low Power"
#define SND_USE_CASE_VERB_VOICECALL "Voice Call"
參考帶有 SND_USE_CASE_DEV 前綴的宏,如 SND_USE_CASE_DEV_SPEAKER 來了解已知設(shè)備的完整列表。
#define SND_USE_CASE_DEV_BLUETOOTH "Bluetooth"
#define SND_USE_CASE_DEV_DIRECT "Direct"
#define SND_USE_CASE_DEV_EARPIECE "Earpiece"
#define SND_USE_CASE_DEV_HANDSET "Handset"
#define SND_USE_CASE_DEV_HDMI "HDMI"
#define SND_USE_CASE_DEV_HEADPHONES "Headphones"
#define SND_USE_CASE_DEV_HEADSET "Headset"
#define SND_USE_CASE_DEV_LINE "Line"
#define SND_USE_CASE_DEV_MIC "Mic"
#define SND_USE_CASE_DEV_NONE "None"
#define SND_USE_CASE_DEV_SPDIF "SPDIF"
#define SND_USE_CASE_DEV_SPEAKER "Speaker"
#define SND_USE_CASE_DEV_USB "USB"
如果存在多個(gè)同名的設(shè)備,則應(yīng)在這些名稱中添加數(shù)字后綴,如 HDMI1,HDMI2,HDMI3 等等。不允許有數(shù)字間隙。帶數(shù)字的名稱必須是連續(xù)的。為了提高可讀性,可以在名稱和索引之間放置空格(如“Line 1”)。為了此目的,設(shè)備名稱 “Line 1” 和 “Line1” 是相同的。
如果 EnableSequence/DisableSequence 控制硬件中的獨(dú)立路徑,則還建議分割播放和捕獲 UCM 設(shè)備并使用數(shù)字后綴。示例用例:使用筆記本電腦中的集成麥克風(fēng),而不是耳機(jī)中的麥克風(fēng)。
設(shè)備的優(yōu)先級(jí)由優(yōu)先級(jí)值決定(值越高 = 優(yōu)先級(jí)越高)。
參考帶有 SND_USE_CASE_MOD 前綴的宏,如 SND_USE_CASE_MOD_ECHO_REF 來了解已知修飾符的完整列表。
#define SND_USE_CASE_MOD_CAPTURE_MUSIC "Capture Music"
#define SND_USE_CASE_MOD_CAPTURE_VOICE "Capture Voice"
#define SND_USE_CASE_MOD_ECHO_REF "Echo Reference"
#define SND_USE_CASE_MOD_PLAY_MUSIC "Play Music"
#define SND_USE_CASE_MOD_PLAY_TONE "Play Tone"
#define SND_USE_CASE_MOD_PLAY_VOICE "Play Voice"
啟動(dòng)(alsactl)
FixedBootSequence 在每次啟動(dòng)時(shí)執(zhí)行。BootSequence 僅當(dāng)聲卡的配置缺失時(shí)才會(huì)執(zhí)行。目的是讓用戶修改音量或開關(guān)等配置。alsactl 確保持久性(將控制狀態(tài)存儲(chǔ)到 /var 樹并在下次啟動(dòng)時(shí)加載以前的狀態(tài))。

設(shè)備音量
預(yù)計(jì)應(yīng)用程序?qū)⑻幚硪袅吭O(shè)置。如果設(shè)備導(dǎo)出了硬件音量(MixerElem 或 Volume/Switch 值),不建議在 Enable / Disable 序列中為 verbs 或設(shè)備的音量設(shè)置設(shè)定固定值。默認(rèn)的音量設(shè)置應(yīng)該在 BootSequence 中設(shè)置。這種方案的目的是,允許用戶使用 alsactl 聲卡狀態(tài)管理覆蓋默認(rèn)值。
檢查清單:
- 在 BootSequence 中設(shè)置默認(rèn)音量
- Verb 的 EnableSequence 應(yīng)確保所有設(shè)備都已關(guān)閉(混音器路徑),以避免同時(shí)使用設(shè)備 - 先前的狀態(tài)未知(請參閱 disdevall 和 disdev2 命令或創(chuàng)建新的自定義命令序列)

動(dòng)態(tài)配置樹
評(píng)估順序可能看起來和從用戶的角度看到的有點(diǎn)不同。首先,解析標(biāo)準(zhǔn) alsa-lib 配置樹。頂層的所有其它層都與這棵樹一起工作。它可能會(huì)將配置塊從所在的配置文件移動(dòng)到樹內(nèi)部。
Example configuration | Parsed static tree | Identical static tree
----------------------------+-------------------------+-------------------------------
If.1 { | If { | If.1.True.Define.VAR "A"
True.Define.VAR "A" | 1.True.Define.VAR "A" | If.2.True.Define.VAR "C"
} | 2.True.Define.VAR "C" | Define.VAR "B"
Define.VAR "B" | } |
If.2 { | Define.VAR "B" |
True.Define.VAR "C" | |
} | |
即使一個(gè)或兩個(gè)條件都被評(píng)估為真,變量 VAR 也將始終被評(píng)估為 B,因?yàn)榈谝粋€(gè) If 塊位于非嵌套的 Define 之前。在文本配置解析器中第二個(gè) If 塊被附加到第一個(gè) If 塊(配置樹中的 Define 之前)中。
語法
除非另有說明,否則使用語法版本 4。
Syntax 4
包含
有兩種方法可以包含其它配置文件。
靜態(tài)包含
靜態(tài)包含繼承自標(biāo)準(zhǔn) alsa-lib 配置語法。它可以放在配置文件的任何位置。搜索路徑由根 alsa 配置路徑(通常為 /usr/share/alsa 的 ucm2 目錄)組成。
<some/path/file.conf> # include file using the search path
</absolute/path/file.conf> # include file using the absolute path
惰性包含
惰性包含在運(yùn)行時(shí)進(jìn)行評(píng)估。根路徑是 ucm2 樹。絕對包含將 ucm2 絕對路徑附加到指定路徑。相對包含是相對于包含 Include 配置塊的文件而言的。
配置樹評(píng)估
靜態(tài)配置樹的評(píng)估按照特定順序進(jìn)行(見下表)。當(dāng)動(dòng)態(tài)配置樹發(fā)生變化時(shí),將重新啟動(dòng)評(píng)估序列以評(píng)估所有可能的更改(新的 Define 或 Include 或 If 塊)。
| 評(píng)估順序 | 配置塊 | 評(píng)估重啟 |
|---|---|---|
| 1 | Define | No |
| 2 | Include | Yes |
| 3 | If | Yes |
替換
配置樹中的動(dòng)態(tài)樹標(biāo)識(shí)符和指定值被替換。替換字符串如下表所示。
| 替換字符串 | 值 |
|---|---|
| ${OpenName} | 原始 UCM 聲卡名稱(傳給 snd_use_case_mgr_open()) |
| ${ConfLibDir} | 庫頂層配置目錄(如 /usr/share/alsa) |
| ${ConfTopDir} | 頂層 UCM 配置目錄(如 /usr/share/alsa/ucm2) |
| ${ConfDir} | 聲卡的 UCM 配置目錄(如 /usr/share/alsa/ucm2/conf.d/USB-Audio) |
| ${ConfName} | 配置名稱(如 USB-Audio.conf) |
| ${CardNumber} | 真實(shí)的 ALSA 聲卡號(hào)(或者對于虛擬 UCM 聲卡為空字符串) |
| ${CardId} | ALSA 聲卡標(biāo)識(shí)符(參見 snd_ctl_card_info_get_id()) |
| ${CardDriver} | ALSA 聲卡驅(qū)動(dòng)(參見 snd_ctl_card_info_get_driver()) |
| ${CardName} | ALSA 聲卡名稱(參見 snd_ctl_card_info_get_name()) |
| ${CardLongName} | ALSA 聲卡長名稱(參見 snd_ctl_card_info_get_longname()) |
| ${CardComponents} | ALSA 聲卡組件(參見 [snd_ctl_card_info_get_components()](https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html#ga2181aa6bf919fd1342b259d2f3af755b "Get the sound cards "components" property from the given info object.")) |
| ${env:<str>} | 環(huán)境變量 <str> |
| ${sys:<str>} | sysfs 文件 <str> 的內(nèi)容 |
| ${var:<str>} | UCM 解析器變量(使用 Define 塊創(chuàng)建) |
| ${eval:<str>} | 計(jì)算表達(dá)式,如 ($var+2)/3 [Syntax 5] |
| ${find-card:<str>} | 查找聲卡 - 參考 查找聲卡替換 部分 |
| ${find-device:<str>} | 查找設(shè)備 - 參考 查找設(shè)備替換 部分 |
聲卡相關(guān)的這些部分信息,可以通過 alsa-utils 包里的 amixer 工具來查看,如:
$ amixer info
Card default 'pulse'/'PulseAudio'
Mixer name : 'PulseAudio'
Components : ''
Controls : 4
Simple ctrls : 2
amixer 工具實(shí)現(xiàn) info 操作的 info() 函數(shù)定義 (位與 alsa-utils/amixer/amixer.c) 如下:
static int info(void)
{
int err;
snd_ctl_t *handle;
snd_mixer_t *mhandle;
snd_ctl_card_info_t *info;
snd_ctl_elem_list_t *clist;
snd_ctl_card_info_alloca(&info);
snd_ctl_elem_list_alloca(&clist);
if ((err = snd_ctl_open(&handle, card, 0)) < 0) {
error("Control device %s open error: %s", card, snd_strerror(err));
return err;
}
if ((err = snd_ctl_card_info(handle, info)) < 0) {
error("Control device %s hw info error: %s", card, snd_strerror(err));
return err;
}
printf("Card %s '%s'/'%s'\n", card, snd_ctl_card_info_get_id(info),
snd_ctl_card_info_get_longname(info));
printf(" Mixer name : '%s'\n", snd_ctl_card_info_get_mixername(info));
printf(" Components : '%s'\n", snd_ctl_card_info_get_components(info));
if ((err = snd_ctl_elem_list(handle, clist)) < 0) {
error("snd_ctl_elem_list failure: %s", snd_strerror(err));
} else {
printf(" Controls : %i\n", snd_ctl_elem_list_get_count(clist));
}
snd_ctl_close(handle);
if ((err = snd_mixer_open(&mhandle, 0)) < 0) {
error("Mixer open error: %s", snd_strerror(err));
return err;
}
if (smixer_level == 0 && (err = snd_mixer_attach(mhandle, card)) < 0) {
error("Mixer attach %s error: %s", card, snd_strerror(err));
snd_mixer_close(mhandle);
return err;
}
if ((err = snd_mixer_selem_register(mhandle, smixer_level > 0 ? &smixer_options : NULL, NULL)) < 0) {
error("Mixer register error: %s", snd_strerror(err));
snd_mixer_close(mhandle);
return err;
}
err = snd_mixer_load(mhandle);
if (err < 0) {
error("Mixer load %s error: %s", card, snd_strerror(err));
snd_mixer_close(mhandle);
return err;
}
printf(" Simple ctrls : %i\n", snd_mixer_get_count(mhandle));
snd_mixer_close(mhandle);
return 0;
}
amixer info 輸出的信息的格式如下:
Card ${Card} '${CardId}'/'${CardLongName}'
Mixer name : 'PulseAudio'
Components : '${CardComponents}'
Controls : 4
Simple ctrls : 2
${CardComponents} 信息由聲卡驅(qū)動(dòng)程序返回,如 Intel 的 ALC 5651 聲卡的驅(qū)動(dòng) (位于 sound/soc/intel/boards/bytcr_rt5651.c):
snprintf(byt_rt5651_components, sizeof(byt_rt5651_components),
"cfg-spk:%s cfg-mic:%s%s",
(byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ? "1" : "2",
mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)],
(byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) ?
" cfg-hp:lrswap" : "");
byt_rt5651_card.components = byt_rt5651_components;
#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
snprintf(byt_rt5651_long_name, sizeof(byt_rt5651_long_name),
"bytcr-rt5651-%s-spk-%s-mic%s",
(byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ?
"mono" : "stereo",
mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)],
(byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) ?
"-hp-swapped" : "");
byt_rt5651_card.long_name = byt_rt5651_long_name;
#endif
特殊的整個(gè)字符串替換
| 替換字符串 | 值 |
|---|---|
| ${evali:<str>} | 計(jì)算表達(dá)式,如 ($var+2)/3 [Syntax 6];目標(biāo)節(jié)點(diǎn)將是整數(shù);僅在 LibraryConfig 子樹中替換 |
查找聲卡替換
這種替換查找 ALSA 聲卡并返回適當(dāng)?shù)臉?biāo)識(shí)符或聲卡號(hào)(參見返回參數(shù))。
使用示例:
${find-card:field=name,regex='^acp$',return=number}
參數(shù):
| 參數(shù) | 描述 |
|---|---|
| return | 返回值類型 (id, number),默認(rèn)值為 id |
| field | 查找的字段 (id, driver, name, longname, mixername, components) |
| regex | 字段匹配的 regex 字符串 |
查找設(shè)備替換
使用示例:
${find-device:type=pcm,field=name,regex='DMIC'}
| 參數(shù) | 描述 |
|---|---|
| type | 設(shè)備類型 (pcm) |
| stream | stream 類型 (playback, capture),默認(rèn)為 playback |
| field | 查找的字段 (id, name, subname) |
| regex | 字段匹配的 regex 字符串 |
變量定義
可以使用 Define 或 DefineRegex 塊來定義和改變變量。Define 塊如下所示:
Define {
variable1 "a"
variable2 "b"
}
DefineRegex 允許提取子字符串,例如:
DefineRegex.rval {
Regex "(hello)|(regex)"
String "hello, it's my regex"
}
結(jié)果將存儲(chǔ)到變量 rval1 中作為 hello,存儲(chǔ)到變量 rval2 中作為 regex(每個(gè)匹配的子字符串都存儲(chǔ)到帶有序列號(hào)后綴的單獨(dú)變量中)。
例如可以使用 ${var:rval1} 引用替換變量。
宏
宏是為 Syntax 版本 6 添加的。DefineMacro 定義新的宏如下:
DefineMacro.macro1 {
Define.a "${var:__arg1}"
Define.b "${var:__other}"
# Device or any other block may be defined here...
}
宏中的參數(shù)被稱為帶有雙下劃線名稱前綴的變量(如_ variable)。DefineMacro 子樹中的配置塊總是在實(shí)例化時(shí)計(jì)算(包括參數(shù)和變量)。
宏可以使用下列方式實(shí)例化(擴(kuò)展):
# short version
Macro.id1.macro1 "arg1='something 1',other='other x'"
# long version
Macro.id1.macro1 {
arg1 'something 1'
other 'other x'
}
第二個(gè)標(biāo)識(shí)符(示例中的 id1)必須是唯一的,但其內(nèi)容被忽略。它僅僅區(qū)分子樹中的項(xiàng)(允許一個(gè)宏有多個(gè)實(shí)例)。
條件
配置樹計(jì)算支持條件 - If 塊。每個(gè) If 塊必須定義一個(gè) Condition 塊和 True 或 False 塊或兩者。True 或 False 塊將在計(jì)算 Condition 時(shí)合并到父樹(If 塊定義的地方)。
示例:
If.uniqueid {
Condition {
Type String
Haystack "abcd"
Needle "a"
}
True {
Define.a a
define.b b
}
}
True(Type AlwaysTrue)
僅執(zhí)行 True 塊。它可以被用于改變計(jì)算順序,就像 配置樹 段中解釋的那樣。
字符串是空 (Type String)
| 字段 | 描述 |
|---|---|
| Empty | 字符串 |
字符串相等 (Type String)
| 字段 | 描述 |
|---|---|
| String1 | 字符串 |
| String2 | 字符串中的子字符串 |
子字符串存在 (Type String)
| 字段 | 描述 |
|---|---|
| Haystack | 字符串 |
| Needle | 字符串中的子字符串 |
Regex 匹配 (Type RegexMatch)
| 字段 | 描述 |
|---|---|
| String | 字符串 |
| Regex | regex 表達(dá)式(擴(kuò)展的 posix,忽略大小寫) |
ALSA 控制元素存在 (Type ControlExists)
| 字段 | 描述 |
|---|---|
| Device | ALSA 控制設(shè)備(參考 snd_ctl_open()) |
| Control | ASCII 形式的控制項(xiàng)(使用 snd_ctl_ascii_elem_id_parse() 解析) |
| ControlEnum | 枚舉控制項(xiàng)的值(可選) |
示例:
If.fmic {
Condition {
Type ControlExists
Control "name='Front Mic Playback Switch'"
}
True {
...
}
}
變體
為了避免在配置更改很少的情況下許多配置文件的重復(fù),而提供了變體擴(kuò)展。變體是為 語法 版本 6 添加的。
下面的示例將創(chuàng)建兩個(gè) verbs - "HiFi" 和 "HiFi 7.1",它們的 "Speaker" 設(shè)備具有不同的播放通道數(shù)(2 和 8)。
示例(主配置文件):
SectionUseCase."HiFi" {
File "HiFi.conf"
Variant."HiFi" {
Comment "HiFi"
}
Variant."HiFi 7+1" {
Comment "HiFi 7.1"
}
}
示例(verb 配置文件 - HiFi.conf):
SectionDevice."Speaker" {
Value {
PlaybackChannels 2
}
Variant."HiFi 7+1".Value {
PlaybackChannels 8
}
}
原文。
Done.