1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  This library is free software; you can redistribute it and/or
3d5ac70f0Sopenharmony_ci *  modify it under the terms of the GNU Lesser General Public
4d5ac70f0Sopenharmony_ci *  License as published by the Free Software Foundation; either
5d5ac70f0Sopenharmony_ci *  version 2 of the License, or (at your option) any later version.
6d5ac70f0Sopenharmony_ci *
7d5ac70f0Sopenharmony_ci *  This library is distributed in the hope that it will be useful,
8d5ac70f0Sopenharmony_ci *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9d5ac70f0Sopenharmony_ci *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10d5ac70f0Sopenharmony_ci *  Lesser General Public License for more details.
11d5ac70f0Sopenharmony_ci *
12d5ac70f0Sopenharmony_ci *  You should have received a copy of the GNU Lesser General Public
13d5ac70f0Sopenharmony_ci *  License along with this library; if not, write to the Free Software
14d5ac70f0Sopenharmony_ci *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
15d5ac70f0Sopenharmony_ci *
16d5ac70f0Sopenharmony_ci *  Support for the verb/device/modifier core logic and API,
17d5ac70f0Sopenharmony_ci *  command line tool and file parser was kindly sponsored by
18d5ac70f0Sopenharmony_ci *  Texas Instruments Inc.
19d5ac70f0Sopenharmony_ci *  Support for multiple active modifiers and devices,
20d5ac70f0Sopenharmony_ci *  transition sequences, multiple client access and user defined use
21d5ac70f0Sopenharmony_ci *  cases was kindly sponsored by Wolfson Microelectronics PLC.
22d5ac70f0Sopenharmony_ci *
23d5ac70f0Sopenharmony_ci *  Copyright (C) 2021 Red Hat Inc.
24d5ac70f0Sopenharmony_ci *  Authors: Jaroslav Kysela <perex@perex.cz>
25d5ac70f0Sopenharmony_ci */
26d5ac70f0Sopenharmony_ci
27d5ac70f0Sopenharmony_ci/**
28d5ac70f0Sopenharmony_ci *  \defgroup ucm_conf Use Case Configuration
29d5ac70f0Sopenharmony_ci *  The ALSA Use Case Configuration.
30d5ac70f0Sopenharmony_ci *  See \ref Usecase_conf page for more details.
31d5ac70f0Sopenharmony_ci *  \{
32d5ac70f0Sopenharmony_ci */
33d5ac70f0Sopenharmony_ci
34d5ac70f0Sopenharmony_ci/*! \page Usecase_conf ALSA Use Case Configuration
35d5ac70f0Sopenharmony_ci
36d5ac70f0Sopenharmony_ciThe use case configuration files use \ref conf syntax to define the
37d5ac70f0Sopenharmony_cistatic configuration tree. This tree is evaluated (modified) at runtime
38d5ac70f0Sopenharmony_ciaccording the conditions and dynamic variables in the configuration tree.
39d5ac70f0Sopenharmony_ciThe result is parsed and exported to the applications using \ref ucm API.
40d5ac70f0Sopenharmony_ci
41d5ac70f0Sopenharmony_ci### Configuration directory and main filename lookup
42d5ac70f0Sopenharmony_ci
43d5ac70f0Sopenharmony_ciThe lookup paths are describen in *ucm.conf* file. The configuration
44d5ac70f0Sopenharmony_cistructure looks like:
45d5ac70f0Sopenharmony_ci
46d5ac70f0Sopenharmony_ci~~~{.html}
47d5ac70f0Sopenharmony_ciUseCasePath.path1 {
48d5ac70f0Sopenharmony_ci  Directory "conf.virt.d"
49d5ac70f0Sopenharmony_ci  File "${OpenName}.conf"
50d5ac70f0Sopenharmony_ci}
51d5ac70f0Sopenharmony_ciUseCasePath.path2 {
52d5ac70f0Sopenharmony_ci  Directory "external"
53d5ac70f0Sopenharmony_ci  File "${OpenName}.conf"
54d5ac70f0Sopenharmony_ci}
55d5ac70f0Sopenharmony_ci~~~
56d5ac70f0Sopenharmony_ci
57d5ac70f0Sopenharmony_ci### UCM main configuration file
58d5ac70f0Sopenharmony_ci
59d5ac70f0Sopenharmony_ciEach sound card has a master sound card file that lists all the supported
60d5ac70f0Sopenharmony_ciuse case verbs for that sound card. i.e.:
61d5ac70f0Sopenharmony_ci
62d5ac70f0Sopenharmony_ci~~~{.html}
63d5ac70f0Sopenharmony_ci# Example master file for blah sound card
64d5ac70f0Sopenharmony_ci# By Joe Blogs <joe@bloggs.org>
65d5ac70f0Sopenharmony_ci
66d5ac70f0Sopenharmony_ciSyntax 6
67d5ac70f0Sopenharmony_ci
68d5ac70f0Sopenharmony_ci# Use Case name for user interface
69d5ac70f0Sopenharmony_ciComment "Nice Abstracted Soundcard"
70d5ac70f0Sopenharmony_ci
71d5ac70f0Sopenharmony_ci# The file is divided into Use case sections. One section per use case verb.
72d5ac70f0Sopenharmony_ci
73d5ac70f0Sopenharmony_ciSectionUseCase."Voice Call" {
74d5ac70f0Sopenharmony_ci  File "voice_call_blah"
75d5ac70f0Sopenharmony_ci  Comment "Make a voice phone call."
76d5ac70f0Sopenharmony_ci}
77d5ac70f0Sopenharmony_ci
78d5ac70f0Sopenharmony_ciSectionUseCase."HiFi" {
79d5ac70f0Sopenharmony_ci  File "hifi_blah"
80d5ac70f0Sopenharmony_ci  Comment "Play and record HiFi quality Music."
81d5ac70f0Sopenharmony_ci}
82d5ac70f0Sopenharmony_ci
83d5ac70f0Sopenharmony_ci# Define Value defaults
84d5ac70f0Sopenharmony_ci
85d5ac70f0Sopenharmony_ciValueDefaults {
86d5ac70f0Sopenharmony_ci  PlaybackChannels 4
87d5ac70f0Sopenharmony_ci  CaptureChannels 4
88d5ac70f0Sopenharmony_ci}
89d5ac70f0Sopenharmony_ci
90d5ac70f0Sopenharmony_ci# Define boot / initialization sequence
91d5ac70f0Sopenharmony_ci# This sequence is skipped, when the soundcard was already configured by system
92d5ac70f0Sopenharmony_ci# (alsactl configuration was already created). The purpose is to not alter
93d5ac70f0Sopenharmony_ci# ALSA card controls which may be modified by user after initial settings.
94d5ac70f0Sopenharmony_ci
95d5ac70f0Sopenharmony_ciBootSequence [
96d5ac70f0Sopenharmony_ci  cset "name='Master Playback Switch',index=2 0,0"
97d5ac70f0Sopenharmony_ci  cset "name='Master Playback Volume',index=2 25,25"
98d5ac70f0Sopenharmony_ci  msleep 50
99d5ac70f0Sopenharmony_ci  cset "name='Master Playback Switch',index=2 1,1"
100d5ac70f0Sopenharmony_ci  cset "name='Master Playback Volume',index=2 50,50"
101d5ac70f0Sopenharmony_ci]
102d5ac70f0Sopenharmony_ci
103d5ac70f0Sopenharmony_ci# Define fixed boot sequence
104d5ac70f0Sopenharmony_ci# This sequence is always executed on boot (hotplug).
105d5ac70f0Sopenharmony_ci
106d5ac70f0Sopenharmony_ciFixedBootSequence [
107d5ac70f0Sopenharmony_ci  cset "name='Something to toggle' toggle"
108d5ac70f0Sopenharmony_ci]
109d5ac70f0Sopenharmony_ci~~~
110d5ac70f0Sopenharmony_ci
111d5ac70f0Sopenharmony_ci### UCM verb configuration file
112d5ac70f0Sopenharmony_ci
113d5ac70f0Sopenharmony_ciThe verb configuration file defines devices, modifier and initialization sequences.
114d5ac70f0Sopenharmony_ciIt is something like a sound profile.
115d5ac70f0Sopenharmony_ci
116d5ac70f0Sopenharmony_ci~~~{.html}
117d5ac70f0Sopenharmony_ci# Example Use case verb section for Voice call blah
118d5ac70f0Sopenharmony_ci# By Joe Blogs <joe@blogs.com>
119d5ac70f0Sopenharmony_ci
120d5ac70f0Sopenharmony_ci# verb global section
121d5ac70f0Sopenharmony_ci
122d5ac70f0Sopenharmony_ciSectionVerb {
123d5ac70f0Sopenharmony_ci
124d5ac70f0Sopenharmony_ci  # enable and disable sequences are compulsory
125d5ac70f0Sopenharmony_ci  EnableSequence [
126d5ac70f0Sopenharmony_ci    disdevall ""	# run DisableSequence for all devices
127d5ac70f0Sopenharmony_ci  ]
128d5ac70f0Sopenharmony_ci
129d5ac70f0Sopenharmony_ci  DisableSequence [
130d5ac70f0Sopenharmony_ci    cset "name='Power Save' on"
131d5ac70f0Sopenharmony_ci  ]
132d5ac70f0Sopenharmony_ci
133d5ac70f0Sopenharmony_ci  # Optional transition verb
134d5ac70f0Sopenharmony_ci  TransitionSequence."ToCaseName" [
135d5ac70f0Sopenharmony_ci    disdevall ""	# run DisableSequence for all devices
136d5ac70f0Sopenharmony_ci    msleep 1
137d5ac70f0Sopenharmony_ci  ]
138d5ac70f0Sopenharmony_ci
139d5ac70f0Sopenharmony_ci  # Optional TQ and device values
140d5ac70f0Sopenharmony_ci  Value {
141d5ac70f0Sopenharmony_ci    TQ HiFi
142d5ac70f0Sopenharmony_ci    PlaybackChannels 6
143d5ac70f0Sopenharmony_ci  }
144d5ac70f0Sopenharmony_ci}
145d5ac70f0Sopenharmony_ci
146d5ac70f0Sopenharmony_ci# Each device is described in new section. N devices are allowed
147d5ac70f0Sopenharmony_ci
148d5ac70f0Sopenharmony_ciSectionDevice."Headphones" {
149d5ac70f0Sopenharmony_ci
150d5ac70f0Sopenharmony_ci  SupportedDevice [
151d5ac70f0Sopenharmony_ci    "x"
152d5ac70f0Sopenharmony_ci    "y"
153d5ac70f0Sopenharmony_ci  ]
154d5ac70f0Sopenharmony_ci
155d5ac70f0Sopenharmony_ci  # or (not both)
156d5ac70f0Sopenharmony_ci
157d5ac70f0Sopenharmony_ci  ConflictingDevice [
158d5ac70f0Sopenharmony_ci    "x"
159d5ac70f0Sopenharmony_ci    "y"
160d5ac70f0Sopenharmony_ci  ]
161d5ac70f0Sopenharmony_ci
162d5ac70f0Sopenharmony_ci  EnableSequence [
163d5ac70f0Sopenharmony_ci    ...
164d5ac70f0Sopenharmony_ci  ]
165d5ac70f0Sopenharmony_ci
166d5ac70f0Sopenharmony_ci  DisableSequence [
167d5ac70f0Sopenharmony_ci    ...
168d5ac70f0Sopenharmony_ci  ]
169d5ac70f0Sopenharmony_ci
170d5ac70f0Sopenharmony_ci  TransitionSequence."ToDevice" [
171d5ac70f0Sopenharmony_ci    ...
172d5ac70f0Sopenharmony_ci  ]
173d5ac70f0Sopenharmony_ci
174d5ac70f0Sopenharmony_ci  Value {
175d5ac70f0Sopenharmony_ci    PlaybackVolume "name='Master Playback Volume',index=2"
176d5ac70f0Sopenharmony_ci    PlaybackSwitch "name='Master Playback Switch',index=2"
177d5ac70f0Sopenharmony_ci    PlaybackPCM "hw:${CardId},4"
178d5ac70f0Sopenharmony_ci  }
179d5ac70f0Sopenharmony_ci}
180d5ac70f0Sopenharmony_ci
181d5ac70f0Sopenharmony_ci# Each modifier is described in new section. N modifiers are allowed
182d5ac70f0Sopenharmony_ci
183d5ac70f0Sopenharmony_ciSectionModifier."Capture Voice" {
184d5ac70f0Sopenharmony_ci  Comment "Record voice call"
185d5ac70f0Sopenharmony_ci
186d5ac70f0Sopenharmony_ci  SupportedDevice [
187d5ac70f0Sopenharmony_ci    "x"
188d5ac70f0Sopenharmony_ci    "y"
189d5ac70f0Sopenharmony_ci  ]
190d5ac70f0Sopenharmony_ci
191d5ac70f0Sopenharmony_ci  # or (not both)
192d5ac70f0Sopenharmony_ci
193d5ac70f0Sopenharmony_ci  ConflictingDevice [
194d5ac70f0Sopenharmony_ci    "x"
195d5ac70f0Sopenharmony_ci    "y"
196d5ac70f0Sopenharmony_ci  ]
197d5ac70f0Sopenharmony_ci
198d5ac70f0Sopenharmony_ci  EnableSequence [
199d5ac70f0Sopenharmony_ci    ...
200d5ac70f0Sopenharmony_ci  ]
201d5ac70f0Sopenharmony_ci
202d5ac70f0Sopenharmony_ci  DisableSequence [
203d5ac70f0Sopenharmony_ci    ...
204d5ac70f0Sopenharmony_ci  ]
205d5ac70f0Sopenharmony_ci
206d5ac70f0Sopenharmony_ci  TransitionSequence."ToModifierName" [
207d5ac70f0Sopenharmony_ci    ...
208d5ac70f0Sopenharmony_ci  ]
209d5ac70f0Sopenharmony_ci
210d5ac70f0Sopenharmony_ci  # Optional TQ and ALSA PCMs
211d5ac70f0Sopenharmony_ci  Value {
212d5ac70f0Sopenharmony_ci    TQ Voice
213d5ac70f0Sopenharmony_ci    CapturePCM "hw:${CardId},11"
214d5ac70f0Sopenharmony_ci    PlaybackMixerElem "Master"
215d5ac70f0Sopenharmony_ci    PlaybackVolume "name='Master Playback Volume',index=2"
216d5ac70f0Sopenharmony_ci    PlaybackSwitch "name='Master Playback Switch',index=2"
217d5ac70f0Sopenharmony_ci  }
218d5ac70f0Sopenharmony_ci}
219d5ac70f0Sopenharmony_ci~~~
220d5ac70f0Sopenharmony_ci
221d5ac70f0Sopenharmony_ci### Sequence graphs
222d5ac70f0Sopenharmony_ci
223d5ac70f0Sopenharmony_ci\image html ucm-seq-verb.svg
224d5ac70f0Sopenharmony_ci\image html ucm-seq-device.svg
225d5ac70f0Sopenharmony_ci
226d5ac70f0Sopenharmony_ci### Sequence commands
227d5ac70f0Sopenharmony_ci
228d5ac70f0Sopenharmony_ciCommand name   | Description
229d5ac70f0Sopenharmony_ci---------------|----------------------------------------------
230d5ac70f0Sopenharmony_cienadev2 ARG    | execute device enable sequence
231d5ac70f0Sopenharmony_cidisdev2 ARG    | execute device disable sequence
232d5ac70f0Sopenharmony_cidisdevall ""   | execute device disable sequence for all devices in verb
233d5ac70f0Sopenharmony_cicdev ARG       | ALSA control device name for snd_ctl_open()
234d5ac70f0Sopenharmony_cicset ARG       | ALSA control set - snd_ctl_ascii_elem_id_parse() + snd_ctl_ascii_value_parse()
235d5ac70f0Sopenharmony_cicset-new ARG   | Create new ALSA user control element - snd_ctl_ascii_elem_id_parse() + description
236d5ac70f0Sopenharmony_cictl-remove ARG | Remove ALSA user control element - snd_ctl_ascii_elem_id_parse()
237d5ac70f0Sopenharmony_cisysw ARG       | write to sysfs tree
238d5ac70f0Sopenharmony_ciusleep ARG     | sleep for specified amount of microseconds
239d5ac70f0Sopenharmony_cimsleep ARG     | sleep for specified amount of milliseconds
240d5ac70f0Sopenharmony_ciexec ARG       | execute a specific command (without shell - *man execv*)
241d5ac70f0Sopenharmony_cishell ARG      | execute a specific command (using shell - *man system*)
242d5ac70f0Sopenharmony_cicfg-save ARG   | save LibraryConfig to a file
243d5ac70f0Sopenharmony_ci
244d5ac70f0Sopenharmony_ci~~~{.html}
245d5ac70f0Sopenharmony_ci# Examples
246d5ac70f0Sopenharmony_cicset "name='PCM Playback Volue',index=2 99"
247d5ac70f0Sopenharmony_cicset-new "name='Bool2' type=bool,count=2 1,0"
248d5ac70f0Sopenharmony_cicset-new "name='Enum' type=enum,labels='L1;L2;L3' 'L2'"
249d5ac70f0Sopenharmony_cictl-remove "name='Bool2'"
250d5ac70f0Sopenharmony_cisysw "-/class/sound/ctl-led/speaker/card${CardNumber}/attach:Speaker Channel Switch"
251d5ac70f0Sopenharmony_ciusleep 10
252d5ac70f0Sopenharmony_ciexec "/bin/echo hello"
253d5ac70f0Sopenharmony_cishell "set"
254d5ac70f0Sopenharmony_cicfg-save "/tmp/test.conf:+pcm"
255d5ac70f0Sopenharmony_ci~~~
256d5ac70f0Sopenharmony_ci
257d5ac70f0Sopenharmony_ci### Naming (devices, verbs)
258d5ac70f0Sopenharmony_ci
259d5ac70f0Sopenharmony_ciSee the SND_USE_CASE_VERB constains like #SND_USE_CASE_VERB_HIFI for the full list of known verbs.
260d5ac70f0Sopenharmony_ci
261d5ac70f0Sopenharmony_ciSee the SND_USE_CASE_DEV constants like #SND_USE_CASE_DEV_SPEAKER for the full list of known devices.
262d5ac70f0Sopenharmony_ciIf multiple devices with the same name exists, the number suffixes should
263d5ac70f0Sopenharmony_cibe added to these names like HDMI1,HDMI2,HDMI3 etc. No number gaps are
264d5ac70f0Sopenharmony_ciallowed. The names with numbers must be continuous. It is allowed to put
265d5ac70f0Sopenharmony_cia whitespace between name and index (like 'Line 1') for the better
266d5ac70f0Sopenharmony_cireadability. The device names 'Line 1' and 'Line1' are equal for
267d5ac70f0Sopenharmony_cithis purpose.
268d5ac70f0Sopenharmony_ci
269d5ac70f0Sopenharmony_ciIf EnableSequence/DisableSequence controls independent paths in the hardware
270d5ac70f0Sopenharmony_ciit is also recommended to split playback and capture UCM devices and use
271d5ac70f0Sopenharmony_cithe number suffixes. Example use case: Use the integrated microphone
272d5ac70f0Sopenharmony_ciin the laptop instead the microphone in headphones.
273d5ac70f0Sopenharmony_ci
274d5ac70f0Sopenharmony_ciThe preference of the devices is determined by the priority value (higher value = higher priority).
275d5ac70f0Sopenharmony_ci
276d5ac70f0Sopenharmony_ciSee the SND_USE_CASE_MOD constants like #SND_USE_CASE_MOD_ECHO_REF for the full list of known modifiers.
277d5ac70f0Sopenharmony_ci
278d5ac70f0Sopenharmony_ci### Boot (alsactl)
279d5ac70f0Sopenharmony_ci
280d5ac70f0Sopenharmony_ciThe *FixedBootSequence* is executed at each boot. The *BootSequence* is executed only
281d5ac70f0Sopenharmony_ciif the card's configuration is missing. The purpose is to let the users modify the
282d5ac70f0Sopenharmony_ciconfiguration like volumes or switches. The alsactl ensures the persistency (store
283d5ac70f0Sopenharmony_cithe state of the controls to the /var tree and loads the previous state in the next
284d5ac70f0Sopenharmony_ciboot).
285d5ac70f0Sopenharmony_ci
286d5ac70f0Sopenharmony_ci\image html ucm-seq-boot.svg
287d5ac70f0Sopenharmony_ci
288d5ac70f0Sopenharmony_ci### Device volume
289d5ac70f0Sopenharmony_ci
290d5ac70f0Sopenharmony_ciIt is expected that the applications handle the volume settings. It is not recommended
291d5ac70f0Sopenharmony_cito set the fixed values for the volume settings in the Enable / Disable sequences for
292d5ac70f0Sopenharmony_civerbs or devices, if the device exports the hardware volume (MixerElem or Volume/Switch
293d5ac70f0Sopenharmony_civalues). The default volume settings should be set in the *BootSequence*. The purpose
294d5ac70f0Sopenharmony_cifor this scheme is to allow users to override defaults using the alsactl sound card
295d5ac70f0Sopenharmony_cistate management.
296d5ac70f0Sopenharmony_ci
297d5ac70f0Sopenharmony_ciChecklist:
298d5ac70f0Sopenharmony_ci
299d5ac70f0Sopenharmony_ci1. Set default volume in BootSequence
300d5ac70f0Sopenharmony_ci2. Verb's EnableSequence should ensure that all devices are turned off (mixer paths)
301d5ac70f0Sopenharmony_ci   to avoid simultaneous device use - the previous state is unknown (see *disdevall*
302d5ac70f0Sopenharmony_ci   and *disdev2* commands or create a new custom command sequence)
303d5ac70f0Sopenharmony_ci
304d5ac70f0Sopenharmony_ci\image html ucm-volume.svg
305d5ac70f0Sopenharmony_ci
306d5ac70f0Sopenharmony_ci### Dynamic configuration tree
307d5ac70f0Sopenharmony_ci
308d5ac70f0Sopenharmony_ciThe evaluation order may look a bit different from the user perspective.
309d5ac70f0Sopenharmony_ciAt first, the standard alsa-lib configuration tree is parsed. All other
310d5ac70f0Sopenharmony_cilayers on top are working with this tree. It may shift / move the configuration
311d5ac70f0Sopenharmony_ciblocks from the configuration files as they are placed to the tree internally.
312d5ac70f0Sopenharmony_ci
313d5ac70f0Sopenharmony_ci~~~{.html}
314d5ac70f0Sopenharmony_ciExample configuration       | Parsed static tree      | Identical static tree
315d5ac70f0Sopenharmony_ci----------------------------+-------------------------+-------------------------------
316d5ac70f0Sopenharmony_ciIf.1 {                      | If {                    | If.1.True.Define.VAR "A"
317d5ac70f0Sopenharmony_ci  True.Define.VAR "A"       |   1.True.Define.VAR "A" | If.2.True.Define.VAR "C"
318d5ac70f0Sopenharmony_ci}                           |   2.True.Define.VAR "C" | Define.VAR "B"
319d5ac70f0Sopenharmony_ciDefine.VAR "B"              | }                       |
320d5ac70f0Sopenharmony_ciIf.2 {                      | Define.VAR "B"          |
321d5ac70f0Sopenharmony_ci  True.Define.VAR "C"       |                         |
322d5ac70f0Sopenharmony_ci}                           |                         |
323d5ac70f0Sopenharmony_ci~~~
324d5ac70f0Sopenharmony_ci
325d5ac70f0Sopenharmony_ciEven if one or both conditions are evaluated as true, the variable _VAR_ will
326d5ac70f0Sopenharmony_cibe evaluated always as **B** because the first _If_ block was before the non-nested
327d5ac70f0Sopenharmony_ci_Define_ . The second _If_ block was appended to the first _If_ block (before
328d5ac70f0Sopenharmony_ci_Define_ in the configuration tree) in the text configuration parser.
329d5ac70f0Sopenharmony_ci
330d5ac70f0Sopenharmony_ci
331d5ac70f0Sopenharmony_ci### Syntax
332d5ac70f0Sopenharmony_ci
333d5ac70f0Sopenharmony_ciUnless described, the syntax version 4 is used.
334d5ac70f0Sopenharmony_ci
335d5ac70f0Sopenharmony_ci~~~
336d5ac70f0Sopenharmony_ciSyntax 4
337d5ac70f0Sopenharmony_ci~~~
338d5ac70f0Sopenharmony_ci
339d5ac70f0Sopenharmony_ci
340d5ac70f0Sopenharmony_ci### Include
341d5ac70f0Sopenharmony_ci
342d5ac70f0Sopenharmony_ciThere are two ways to include other configuration files.
343d5ac70f0Sopenharmony_ci
344d5ac70f0Sopenharmony_ci#### Static include
345d5ac70f0Sopenharmony_ci
346d5ac70f0Sopenharmony_ciThe static include is inherited from the standard alsa-lib configuration
347d5ac70f0Sopenharmony_cisyntax. It can be placed anywhere in the configuration files. The search
348d5ac70f0Sopenharmony_cipath is composed from the root alsa configuration path (usually
349d5ac70f0Sopenharmony_ci_/usr/share/alsa_) and _ucm2_ directory.
350d5ac70f0Sopenharmony_ci
351d5ac70f0Sopenharmony_ci~~~{.html}
352d5ac70f0Sopenharmony_ci<some/path/file.conf>        # include file using the search path
353d5ac70f0Sopenharmony_ci</absolute/path/file.conf>   # include file using the absolute path
354d5ac70f0Sopenharmony_ci~~~
355d5ac70f0Sopenharmony_ci
356d5ac70f0Sopenharmony_ci#### Lazy include
357d5ac70f0Sopenharmony_ci
358d5ac70f0Sopenharmony_ciThe lazy include is evaluated at runtime. The root path is the ucm2
359d5ac70f0Sopenharmony_citree. The absolute include appends the ucm2 absolute path to the
360d5ac70f0Sopenharmony_cispecified path. The relative include is relative to the file which
361d5ac70f0Sopenharmony_cicontains the _Include_ configuration block.
362d5ac70f0Sopenharmony_ci
363d5ac70f0Sopenharmony_ci~~~{.html}
364d5ac70f0Sopenharmony_ciInclude.id1.File "/some/path/file.conf"  # absolute include (in the ucm2 tree)
365d5ac70f0Sopenharmony_ciInclude.id2.File "subdir/file.conf"      # relative include to the current configuration directory (UseCasePath)
366d5ac70f0Sopenharmony_ci~~~
367d5ac70f0Sopenharmony_ci
368d5ac70f0Sopenharmony_ci### Configuration tree evaluation
369d5ac70f0Sopenharmony_ci
370d5ac70f0Sopenharmony_ciThe evaluation of the static configuration tree is proceed in
371d5ac70f0Sopenharmony_cithe specific order (see table bellow). When the dynamic configuration
372d5ac70f0Sopenharmony_citree changes, the evaluation sequence is restarted to evaluate
373d5ac70f0Sopenharmony_ciall possible changes (new *Define* or *Include* or *If* blocks).
374d5ac70f0Sopenharmony_ci
375d5ac70f0Sopenharmony_ciEvaluation order   | Configuration block | Evaluation restart
376d5ac70f0Sopenharmony_ci------------------:|---------------------|--------------------
377d5ac70f0Sopenharmony_ci1                  | Define              | No
378d5ac70f0Sopenharmony_ci2                  | Include             | Yes
379d5ac70f0Sopenharmony_ci3                  | If                  | Yes
380d5ac70f0Sopenharmony_ci
381d5ac70f0Sopenharmony_ci
382d5ac70f0Sopenharmony_ci### Substitutions
383d5ac70f0Sopenharmony_ci
384d5ac70f0Sopenharmony_ciThe dynamic tree identifiers and assigned values in the configuration tree are
385d5ac70f0Sopenharmony_cisubstituted. The substitutes strings are in the table bellow.
386d5ac70f0Sopenharmony_ci
387d5ac70f0Sopenharmony_ciSubstituted string   | Value
388d5ac70f0Sopenharmony_ci---------------------|---------------------
389d5ac70f0Sopenharmony_ci${OpenName}          | Original UCM card name (passed to snd_use_case_mgr_open())
390d5ac70f0Sopenharmony_ci${ConfLibDir}        | Library top-level configuration directory (e.g. /usr/share/alsa)
391d5ac70f0Sopenharmony_ci${ConfTopDir}        | Top-level UCM configuration directory (e.g. /usr/share/alsa/ucm2)
392d5ac70f0Sopenharmony_ci${ConfDir}           | Card's UCM configuration directory (e.g. /usr/share/alsa/ucm2/conf.d/USB-Audio)
393d5ac70f0Sopenharmony_ci${ConfName}          | Configuration name (e.g. USB-Audio.conf)
394d5ac70f0Sopenharmony_ci${CardNumber}        | Real ALSA card number (or empty string for the virtual UCM card)
395d5ac70f0Sopenharmony_ci${CardId}            | ALSA card identifier (see snd_ctl_card_info_get_id())
396d5ac70f0Sopenharmony_ci${CardDriver}        | ALSA card driver (see snd_ctl_card_info_get_driver())
397d5ac70f0Sopenharmony_ci${CardName}          | ALSA card name (see snd_ctl_card_info_get_name())
398d5ac70f0Sopenharmony_ci${CardLongName}      | ALSA card long name (see snd_ctl_card_info_get_longname())
399d5ac70f0Sopenharmony_ci${CardComponents}    | ALSA card components (see snd_ctl_card_info_get_components())
400d5ac70f0Sopenharmony_ci${env:\<str\>}         | Environment variable \<str\>
401d5ac70f0Sopenharmony_ci${sys:\<str\>}         | Contents of sysfs file \<str\>
402d5ac70f0Sopenharmony_ci${var:\<str\>}         | UCM parser variable (set using a _Define_ block)
403d5ac70f0Sopenharmony_ci${eval:\<str\>}        | Evaluate expression like *($var+2)/3* [**Syntax 5**]
404d5ac70f0Sopenharmony_ci${find-card:\<str\>}   | Find a card - see _Find card substitution_ section
405d5ac70f0Sopenharmony_ci${find-device:\<str\>} | Find a device - see _Find device substitution_ section
406d5ac70f0Sopenharmony_ci
407d5ac70f0Sopenharmony_ci#### Special whole string substitution
408d5ac70f0Sopenharmony_ci
409d5ac70f0Sopenharmony_ciSubstituted string   | Value
410d5ac70f0Sopenharmony_ci---------------------|---------------------
411d5ac70f0Sopenharmony_ci${evali:\<str\>}       | Evaluate expression like *($var+2)/3* [**Syntax 6**]; target node will be integer; substituted only in the LibraryConfig subtree
412d5ac70f0Sopenharmony_ci
413d5ac70f0Sopenharmony_ci#### Find card substitution
414d5ac70f0Sopenharmony_ci
415d5ac70f0Sopenharmony_ciThis substitutions finds the ALSA card and returns the appropriate identifier or
416d5ac70f0Sopenharmony_cithe card number (see return argument).
417d5ac70f0Sopenharmony_ci
418d5ac70f0Sopenharmony_ciUsage example:
419d5ac70f0Sopenharmony_ci
420d5ac70f0Sopenharmony_ci~~~{.html}
421d5ac70f0Sopenharmony_ci${find-card:field=name,regex='^acp$',return=number}
422d5ac70f0Sopenharmony_ci~~~
423d5ac70f0Sopenharmony_ci
424d5ac70f0Sopenharmony_ciArguments:
425d5ac70f0Sopenharmony_ci
426d5ac70f0Sopenharmony_ciArgument             | Description
427d5ac70f0Sopenharmony_ci---------------------|-----------------------
428d5ac70f0Sopenharmony_cireturn               | return value type (id, number), id is the default
429d5ac70f0Sopenharmony_cifield                | field for the lookup (id, driver, name, longname, mixername, components)
430d5ac70f0Sopenharmony_ciregex                | regex string for the field match
431d5ac70f0Sopenharmony_ci
432d5ac70f0Sopenharmony_ci#### Find device substitution
433d5ac70f0Sopenharmony_ci
434d5ac70f0Sopenharmony_ciUsage example:
435d5ac70f0Sopenharmony_ci
436d5ac70f0Sopenharmony_ci~~~{.html}
437d5ac70f0Sopenharmony_ci${find-device:type=pcm,field=name,regex='DMIC'}
438d5ac70f0Sopenharmony_ci~~~
439d5ac70f0Sopenharmony_ci
440d5ac70f0Sopenharmony_ciArguments:
441d5ac70f0Sopenharmony_ci
442d5ac70f0Sopenharmony_ciArgument             | Description
443d5ac70f0Sopenharmony_ci---------------------|-----------------------
444d5ac70f0Sopenharmony_citype                 | device type (pcm)
445d5ac70f0Sopenharmony_cistream               | stream type (playback, capture), playback is default
446d5ac70f0Sopenharmony_cifield                | field for the lookup (id, name, subname)
447d5ac70f0Sopenharmony_ciregex                | regex string for the field match
448d5ac70f0Sopenharmony_ci
449d5ac70f0Sopenharmony_ci
450d5ac70f0Sopenharmony_ci### Variable defines
451d5ac70f0Sopenharmony_ci
452d5ac70f0Sopenharmony_ciThe variables can be defined and altered with the *Define* or *DefineRegex* blocks.
453d5ac70f0Sopenharmony_ciThe *Define* block looks like:
454d5ac70f0Sopenharmony_ci
455d5ac70f0Sopenharmony_ci~~~{.html}
456d5ac70f0Sopenharmony_ciDefine {
457d5ac70f0Sopenharmony_ci  variable1 "a"
458d5ac70f0Sopenharmony_ci  variable2 "b"
459d5ac70f0Sopenharmony_ci}
460d5ac70f0Sopenharmony_ci~~~
461d5ac70f0Sopenharmony_ci
462d5ac70f0Sopenharmony_ciThe *DefineRegex* allows substring extraction like:
463d5ac70f0Sopenharmony_ci
464d5ac70f0Sopenharmony_ci~~~{.html}
465d5ac70f0Sopenharmony_ciDefineRegex.rval {
466d5ac70f0Sopenharmony_ci  Regex "(hello)|(regex)"
467d5ac70f0Sopenharmony_ci  String "hello, it's my regex"
468d5ac70f0Sopenharmony_ci}
469d5ac70f0Sopenharmony_ci~~~
470d5ac70f0Sopenharmony_ci
471d5ac70f0Sopenharmony_ciThe result will be stored to variables *rval1* as *hello* and *rval2* as *regex* (every matched
472d5ac70f0Sopenharmony_cisubstrings are stored to a separate variable with the sequence number postfix.
473d5ac70f0Sopenharmony_ci
474d5ac70f0Sopenharmony_ciVariables can be substituted using the `${var:rval1}` reference for example.
475d5ac70f0Sopenharmony_ci
476d5ac70f0Sopenharmony_ci### Macros
477d5ac70f0Sopenharmony_ci
478d5ac70f0Sopenharmony_ciMacros were added for *Syntax* version *6*. The *DefineMacro* defines new
479d5ac70f0Sopenharmony_cimacro like:
480d5ac70f0Sopenharmony_ci
481d5ac70f0Sopenharmony_ci~~~{.html}
482d5ac70f0Sopenharmony_ciDefineMacro.macro1 {
483d5ac70f0Sopenharmony_ci  Define.a "${var:__arg1}"
484d5ac70f0Sopenharmony_ci  Define.b "${var:__other}"
485d5ac70f0Sopenharmony_ci  # Device or any other block may be defined here...
486d5ac70f0Sopenharmony_ci}
487d5ac70f0Sopenharmony_ci~~~
488d5ac70f0Sopenharmony_ci
489d5ac70f0Sopenharmony_ciThe arguments in the macro are refered as the variables with the double
490d5ac70f0Sopenharmony_ciunderscore name prefix (like *__variable*). The configuration block in
491d5ac70f0Sopenharmony_cithe DefineMacro subtree is always evaluated (including arguments and variables)
492d5ac70f0Sopenharmony_ciat the time of the instantiation.
493d5ac70f0Sopenharmony_ci
494d5ac70f0Sopenharmony_ciThe macros can be instantiated (expanded) using:
495d5ac70f0Sopenharmony_ci
496d5ac70f0Sopenharmony_ci~~~{.html}
497d5ac70f0Sopenharmony_ci# short version
498d5ac70f0Sopenharmony_ciMacro.id1.macro1 "arg1='something 1',other='other x'"
499d5ac70f0Sopenharmony_ci
500d5ac70f0Sopenharmony_ci# long version
501d5ac70f0Sopenharmony_ciMacro.id1.macro1 {
502d5ac70f0Sopenharmony_ci  arg1 'something 1'
503d5ac70f0Sopenharmony_ci  other 'other x'
504d5ac70f0Sopenharmony_ci}
505d5ac70f0Sopenharmony_ci~~~
506d5ac70f0Sopenharmony_ci
507d5ac70f0Sopenharmony_ciThe second identifier (in example as *id1*) must be unique, but the contents
508d5ac70f0Sopenharmony_ciis ignored. It just differentiate the items in the subtree (allowing multiple
509d5ac70f0Sopenharmony_ciinstances for one macro).
510d5ac70f0Sopenharmony_ci
511d5ac70f0Sopenharmony_ci### Conditions
512d5ac70f0Sopenharmony_ci
513d5ac70f0Sopenharmony_ciThe configuration tree evaluation supports the conditions - *If* blocks. Each *If* blocks
514d5ac70f0Sopenharmony_cimust define a *Condition* block and *True* or *False* blocks or both. The *True* or *False*
515d5ac70f0Sopenharmony_ciblocks will be merged to the parent tree (where the *If* block is defined) when
516d5ac70f0Sopenharmony_cithe *Condition* is evaluated.
517d5ac70f0Sopenharmony_ci
518d5ac70f0Sopenharmony_ciExample:
519d5ac70f0Sopenharmony_ci
520d5ac70f0Sopenharmony_ci~~~{.html}
521d5ac70f0Sopenharmony_ciIf.uniqueid {
522d5ac70f0Sopenharmony_ci  Condition {
523d5ac70f0Sopenharmony_ci    Type String
524d5ac70f0Sopenharmony_ci    Haystack "abcd"
525d5ac70f0Sopenharmony_ci    Needle "a"
526d5ac70f0Sopenharmony_ci  }
527d5ac70f0Sopenharmony_ci  True {
528d5ac70f0Sopenharmony_ci    Define.a a
529d5ac70f0Sopenharmony_ci    define.b b
530d5ac70f0Sopenharmony_ci  }
531d5ac70f0Sopenharmony_ci}
532d5ac70f0Sopenharmony_ci~~~
533d5ac70f0Sopenharmony_ci
534d5ac70f0Sopenharmony_ci#### True (Type AlwaysTrue)
535d5ac70f0Sopenharmony_ci
536d5ac70f0Sopenharmony_ciExecute only *True* block. It may be used to change the evaluation order as
537d5ac70f0Sopenharmony_ciexplained in the *Configuration Tree* paragraph.
538d5ac70f0Sopenharmony_ci
539d5ac70f0Sopenharmony_ci#### String is empty (Type String)
540d5ac70f0Sopenharmony_ci
541d5ac70f0Sopenharmony_ciField                | Description
542d5ac70f0Sopenharmony_ci---------------------|-----------------------
543d5ac70f0Sopenharmony_ciEmpty                | string
544d5ac70f0Sopenharmony_ci
545d5ac70f0Sopenharmony_ci#### Strings are equal (Type String)
546d5ac70f0Sopenharmony_ci
547d5ac70f0Sopenharmony_ciField                | Description
548d5ac70f0Sopenharmony_ci---------------------|-----------------------
549d5ac70f0Sopenharmony_ciString1              | string
550d5ac70f0Sopenharmony_ciString2              | substring in string
551d5ac70f0Sopenharmony_ci
552d5ac70f0Sopenharmony_ci#### Substring is present (Type String)
553d5ac70f0Sopenharmony_ci
554d5ac70f0Sopenharmony_ciField                | Description
555d5ac70f0Sopenharmony_ci---------------------|-----------------------
556d5ac70f0Sopenharmony_ciHaystack             | string
557d5ac70f0Sopenharmony_ciNeedle               | substring in string
558d5ac70f0Sopenharmony_ci
559d5ac70f0Sopenharmony_ci#### Regex match (Type RegexMatch)
560d5ac70f0Sopenharmony_ci
561d5ac70f0Sopenharmony_ciField                | Description
562d5ac70f0Sopenharmony_ci---------------------|-----------------------
563d5ac70f0Sopenharmony_ciString               | string
564d5ac70f0Sopenharmony_ciRegex                | regex expression (extended posix, ignore case)
565d5ac70f0Sopenharmony_ci
566d5ac70f0Sopenharmony_ci#### ALSA control element exists (Type ControlExists)
567d5ac70f0Sopenharmony_ci
568d5ac70f0Sopenharmony_ciField                | Description
569d5ac70f0Sopenharmony_ci---------------------|-----------------------
570d5ac70f0Sopenharmony_ciDevice               | ALSA control device (see snd_ctl_open())
571d5ac70f0Sopenharmony_ciControl              | control in ASCII (parsed using snd_ctl_ascii_elem_id_parse())
572d5ac70f0Sopenharmony_ciControlEnum	     | value for the enum control (optional)
573d5ac70f0Sopenharmony_ci
574d5ac70f0Sopenharmony_ciExample:
575d5ac70f0Sopenharmony_ci
576d5ac70f0Sopenharmony_ci~~~{.html}
577d5ac70f0Sopenharmony_ciIf.fmic {
578d5ac70f0Sopenharmony_ci  Condition {
579d5ac70f0Sopenharmony_ci    Type ControlExists
580d5ac70f0Sopenharmony_ci    Control "name='Front Mic Playback Switch'"
581d5ac70f0Sopenharmony_ci  }
582d5ac70f0Sopenharmony_ci  True {
583d5ac70f0Sopenharmony_ci    ...
584d5ac70f0Sopenharmony_ci  }
585d5ac70f0Sopenharmony_ci}
586d5ac70f0Sopenharmony_ci~~~
587d5ac70f0Sopenharmony_ci
588d5ac70f0Sopenharmony_ci### Variants
589d5ac70f0Sopenharmony_ci
590d5ac70f0Sopenharmony_ciTo avoid duplication of the many configuration files for the cases with
591d5ac70f0Sopenharmony_ciminimal configuration changes, there is the variant extension. Variants were
592d5ac70f0Sopenharmony_ciadded for *Syntax* version *6*.
593d5ac70f0Sopenharmony_ci
594d5ac70f0Sopenharmony_ciThe bellow example will create two verbs - "HiFi" and "HiFi 7.1" with
595d5ac70f0Sopenharmony_cithe different playback channels (2 and 8) for the "Speaker" device.
596d5ac70f0Sopenharmony_ci
597d5ac70f0Sopenharmony_ciExample (main configuration file):
598d5ac70f0Sopenharmony_ci
599d5ac70f0Sopenharmony_ci~~~{.html}
600d5ac70f0Sopenharmony_ciSectionUseCase."HiFi" {
601d5ac70f0Sopenharmony_ci  File "HiFi.conf"
602d5ac70f0Sopenharmony_ci  Variant."HiFi" {
603d5ac70f0Sopenharmony_ci    Comment "HiFi"
604d5ac70f0Sopenharmony_ci  }
605d5ac70f0Sopenharmony_ci  Variant."HiFi 7+1" {
606d5ac70f0Sopenharmony_ci    Comment "HiFi 7.1"
607d5ac70f0Sopenharmony_ci  }
608d5ac70f0Sopenharmony_ci}
609d5ac70f0Sopenharmony_ci~~~
610d5ac70f0Sopenharmony_ci
611d5ac70f0Sopenharmony_ciExample (verb configuration file - HiFi.conf):
612d5ac70f0Sopenharmony_ci
613d5ac70f0Sopenharmony_ci~~~{.html}
614d5ac70f0Sopenharmony_ciSectionDevice."Speaker" {
615d5ac70f0Sopenharmony_ci  Value {
616d5ac70f0Sopenharmony_ci    PlaybackChannels 2
617d5ac70f0Sopenharmony_ci  }
618d5ac70f0Sopenharmony_ci  Variant."HiFi 7+1".Value {
619d5ac70f0Sopenharmony_ci    PlaybackChannels 8
620d5ac70f0Sopenharmony_ci  }
621d5ac70f0Sopenharmony_ci}
622d5ac70f0Sopenharmony_ci~~~
623d5ac70f0Sopenharmony_ci
624d5ac70f0Sopenharmony_ci*/
625d5ac70f0Sopenharmony_ci
626d5ac70f0Sopenharmony_ci/**
627d5ac70f0Sopenharmony_ci \}
628d5ac70f0Sopenharmony_ci */
629