-/*! \mainpage Index Preamble and License
+/*! \mainpage Index, Preamble and License
\author Jaroslav Kysela <perex@perex.cz>
\author Abramo Bagnara <abramo@alsa-project.org>
\author Takashi Iwai <tiwai@suse.de>
\author Frank van de Pol <fvdpol@coil.demon.nl>
-<H2>Preface</H2>
-<P>The Advanced Linux Sound Architecture (\e ALSA) comes with a kernel
+Preface
+-------
+
+The Advanced Linux Sound Architecture (\e ALSA) comes with a kernel
API and a library API. This document describes the library API and how
-it interfaces with the kernel API.</P>
+it interfaces with the kernel API.
-<H2>Documentation License</H2>
+### Documentation License
-<P>This documentation is free; you can redistribute it without
-any restrictions. Modifications or derived work must retain
-the copyright and list all authors.</P>
+ This documentation is free; you can redistribute it without
+ any restrictions. Modifications or derived work must retain
+ the copyright and list all authors.
-<P>This documentation is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</P>
+ This documentation is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+API usage
+---------
-<H2>API usage</H2>
-<P>Application programmers should use the library API rather than the
+Application programmers should use the library API rather than the
kernel API. The library offers 100% of the functionality of the kernel API,
but adds major improvements in usability, making the application code simpler
and better looking. In addition, future fixes or compatibility code
-may be placed in the library code instead of the kernel driver.</P>
-
-<H2>API links</H2>
-
-<UL>
- <LI>Page \ref control explains the primitive controls API.
- <LI>Page \ref control_plugins explains the design of primitive control plugins.
- <LI>Page \ref hcontrol explains the high-level primitive controls API.
- <LI>Page \ref mixer explains the mixer controls API.
- <LI>Page \ref pcm explains the design of the PCM (digital audio) API.
- <LI>Page \ref pcm_plugins explains the design of PCM (digital audio) plugins.
- <LI>Page \ref pcm_external_plugins explains the external PCM plugin SDK.
- <LI>Page \ref ctl_external_plugins explains the external control plugin SDK.
- <LI>Page \ref rawmidi explains the design of the RawMidi API.
- <LI>Page \ref timer explains the design of the Timer API.
- <LI>Page \ref seq explains the design of the Sequencer API.
- <LI>Page \ref ucm explains the use case API.
- <LI>Page \ref topology explains the DSP topology API.
-</UL>
-
-<H2>Configuration</H2>
-
-<UL>
- <LI>Page \ref conf explains the syntax of library configuration files.
- <LI>Page \ref confarg explains the run-time argument syntax.
- <LI>Page \ref conffunc explains run-time function definitions and their usage.
- <LI>Page \ref confhooks explains run-time hook definitions and their usage.
-</UL>
+may be placed in the library code instead of the kernel driver.
+
+API links
+---------
+
+- Page \subpage control explains the primitive controls API.
+- Page \subpage control_plugins explains the design of primitive control plugins.
+- Page \subpage hcontrol explains the high-level primitive controls API.
+- Page \subpage mixer explains the mixer controls API.
+- Page \subpage pcm explains the design of the PCM (digital audio) API.
+- Page \subpage pcm_plugins explains the design of PCM (digital audio) plugins.
+- Page \subpage pcm_external_plugins explains the external PCM plugin SDK.
+- Page \subpage ctl_external_plugins explains the external control plugin SDK.
+- Page \subpage rawmidi explains the design of the RawMidi API.
+- Page \subpage timer explains the design of the Timer API.
+- Page \subpage seq explains the design of the Sequencer API.
+- Page \subpage ucm explains the use case API.
+- Page \subpage topology explains the DSP topology API.
+
+Configuration
+-------------
+
+- Page \subpage conf explains the syntax of library configuration.
+- Page \subpage confarg explains the run-time argument syntax.
+- Page \subpage conffunc explains run-time function definitions and their usage.
+- Page \subpage confhooks explains run-time hook definitions and their usage.
+- Page \subpage ucm_conf explains the UCM configuration and their usage.
*/
--- /dev/null
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Support for the verb/device/modifier core logic and API,
+ * command line tool and file parser was kindly sponsored by
+ * Texas Instruments Inc.
+ * Support for multiple active modifiers and devices,
+ * transition sequences, multiple client access and user defined use
+ * cases was kindly sponsored by Wolfson Microelectronics PLC.
+ *
+ * Copyright (C) 2021 Red Hat Inc.
+ * Authors: Jaroslav Kysela <perex@perex.cz>
+ */
+
+/**
+ * \defgroup ucm_conf Use Case Configuration
+ * The ALSA Use Case Configuration.
+ * See \ref Usecase_conf page for more details.
+ * \{
+ */
+
+/*! \page Usecase_conf ALSA Use Case Configuration
+
+The use case configuration files use \ref conf syntax to define the
+static configuration tree. This tree is evaluated (modified) at runtime
+according the conditions and dynamic variables in the configuration tree.
+The result is parsed and exported to the applications using \ref ucm API.
+
+### Configuration directory and main filename lookup
+
+The lookup paths are describen in *ucm.conf* file. The configuration
+structure looks like:
+
+~~~{.html}
+UseCasePath.path1 {
+ Directory "conf.virt.d"
+ File "${OpenName}.conf"
+}
+UseCasePath.path2 {
+ Directory "external"
+ File "${OpenName}.conf"
+}
+~~~
+
+### UCM main configuration file
+
+Each sound card has a master sound card file that lists all the supported
+use case verbs for that sound card. i.e.:
+
+~~~{.html}
+# Example master file for blah sound card
+# By Joe Blogs <joe@bloggs.org>
+
+# 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='My control' on"
+]
+
+# Define fixed boot sequence
+# This sequence is always executed on boot (hotplug).
+
+FixedBootSequence [
+ cset "name='Something to toggle' toggle"
+]
+~~~
+
+### UCM verb configuration file
+
+The verb configuration file defines devices, modifier and initialization sequences.
+It is something like a sound profile.
+
+~~~{.html}
+# 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 [
+ 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"
+ ]
+
+ DisableSequence [
+ 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"
+ ]
+
+ # Optional transition verb
+ TransitionSequence."ToCaseName" [
+ 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"
+ PlaybackVolume "name='Master Playback Volume',index=2"
+ PlaybackSwitch "name='Master Playback Switch',index=2"
+ }
+}
+~~~
+
+### Sequence commands
+
+Command name | Description
+---------------|----------------------------------------------
+cdev ARG | ALSA control device name for snd_ctl_open()
+cset ARG | ALSA control set - snd_ctl_ascii_elem_id_parse() + snd_ctl_ascii_value_parse()
+cset-new ARG | Create new ALSA user control element - snd_ctl_ascii_elem_id_parse() + description
+ctl-remove ARG | Remove ALSA user control element - snd_ctl_ascii_elem_id_parse()
+sysw ARG | write to sysfs tree
+usleep ARG | sleep for specified amount of microseconds
+msleep ARG | sleep for specified amount of milliseconds
+exec ARG | execute a specific command (without shell - *man execv*)
+shell ARG | execute a specific command (using shell - *man system*)
+cfg-save ARG | save LibraryConfig to a file
+
+~~~{.html}
+# 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"
+~~~
+
+### Naming (devices, verbs)
+
+See the SND_USE_CASE_VERB constains like #SND_USE_CASE_VERB_HIFI for the full list of known verbs.
+
+See the SND_USE_CASE_DEV constants like #SND_USE_CASE_DEV_SPEAKER for the full list of known devices.
+If multiple devices with the same name exists, the number suffixes should
+be added to these names like HDMI1,HDMI2,HDMI3 etc. No number gaps are
+allowed. The names with numbers must be continuous. It is allowed to put
+a whitespace between name and index (like 'Line 1') for the better
+readability. The device names 'Line 1' and 'Line1' are equal for
+this purpose.
+
+If EnableSequence/DisableSequence controls independent paths in the hardware
+it is also recommended to split playback and capture UCM devices and use
+the number suffixes. Example use case: Use the integrated microphone
+in the laptop instead the microphone in headphones.
+
+The preference of the devices is determined by the priority value (higher value = higher priority).
+
+See the SND_USE_CASE_MOD constants like #SND_USE_CASE_MOD_ECHO_REF for the full list of known modifiers.
+
+### Boot (alsactl)
+
+The *FixedBootSequence* is executed at each boot. The *BootSequence* is executed only
+if the card's configuration is missing. The purpose is to let the users modify the
+configuration like volumes or switches. The alsactl ensures the persistency (store
+the state of the controls to the /var tree and loads the previous state in the next
+boot).
+
+### Device volume
+
+It is expected that the applications handle the volume settings. It is not recommended
+to set the fixed values for the volume settings to the Enable / Disable sequences for
+verbs or devices, if the device exports the hardware volume (MixerElem or Volume/Switch
+values). The default volume settings should be set in the *BootSequence*.
+
+### Dynamic configuration tree
+
+The evaluation order may look a bit different from the user perspective.
+At first, the standard alsa-lib configuration tree is parsed. All other
+layers on top are working with this tree. It may shift / move the configuration
+blocks from the configuration files as they are placed to the tree internally.
+
+~~~{.html}
+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" | |
+} | |
+~~~
+
+Even if one or both conditions are evaluated as true, the variable _VAR_ will
+be evaluated always as **B** because the first _If_ block was before the non-nested
+_Define_ . The second _If_ block was appended to the first _If_ block (before
+_Define_ in the configuration tree) in the text configuration parser.
+
+
+### Syntax
+
+Unless described, the syntax version 4 is used.
+
+~~~
+Syntax 4
+~~~
+
+
+### Include
+
+There are two ways to include other configuration files.
+
+#### Static include
+
+The static include is inherited from the standard alsa-lib configuration
+syntax. It can be placed anywhere in the configuration files. The search
+path is composed from the root alsa configuration path (usually
+_/usr/share/alsa_) and _ucm2_ directory.
+
+~~~{.html}
+<some/path/file.conf> # include file using the search path
+</absolute/path/file.conf> # include file using the absolute path
+~~~
+
+#### Lazy include
+
+The lazy include is evaluated at runtime. The root path is the ucm2
+tree. The absolute include appends the ucm2 absolute path to the
+specified path. The relative include is relative to the file which
+contains the _Include_ configuration block.
+
+~~~{.html}
+Include.id1.File "/some/path/file.conf" # absolute include (in the ucm2 tree)
+Include.id2.File "subdir/file.conf" # relative include to the current configuration directory (UseCasePath)
+~~~
+
+### Configuration tree evaluation
+
+The evaluation of the static configuration tree is proceed in
+the specific order (see table bellow). When the dynamic configuration
+tree changes, the evaluation sequence is restarted to evaluate
+all possible changes (new *Define* or *Include* or *If* blocks).
+
+Evaluation order | Configuration block | Evaluation restart
+------------------:|---------------------|--------------------
+1 | Define | No
+2 | Include | Yes
+3 | If | Yes
+
+
+### Substitutions
+
+The dynamic tree identifiers and assigned values in the configuration tree are
+substituted. The substitutes strings are in the table bellow.
+
+Substituted string | Value
+---------------------|---------------------
+${OpenName} | Original UCM card name (passed to snd_use_case_mgr_open())
+${ConfLibDir} | Library top-level configuration directory (e.g. /usr/share/alsa)
+${ConfTopDir} | Top-level UCM configuration directory (e.g. /usr/share/alsa/ucm2)
+${ConfDir} | Card's UCM configuration directory (e.g. /usr/share/alsa/ucm2/conf.d/USB-Audio)
+${ConfName} | Configuration name (e.g. USB-Audio.conf)
+${CardNumber} | Real ALSA card number (or empty string for the virtual UCM card)
+${CardId} | ALSA card identifier (see snd_ctl_card_info_get_id())
+${CardDriver} | ALSA card driver (see snd_ctl_card_info_get_driver())
+${CardName} | ALSA card name (see snd_ctl_card_info_get_name())
+${CardLongName} | ALSA card long name (see snd_ctl_card_info_get_longname())
+${CardComponents} | ALSA card components (see snd_ctl_card_info_get_components())
+${env:<str>} | Environment variable <str>
+${sys:<str>} | Contents of sysfs file <str>
+${var:<str>} | UCM parser variable (set using a _Define_ block)
+${eval:<str>} | Evaluate expression like *($var+2)/3* [**Syntax 5**]
+${find-card:<str>} | Find a card - see _Find card substitution_ section
+${find-device:<str>} | Find a device - see _Find device substitution_ section
+
+#### Find card substitution
+
+This substitutions finds the ALSA card and returns the appropriate identifier or
+the card number (see return argument).
+
+Usage example:
+
+~~~{.html}
+${find-card:field=name,regex='^acp$',return=number}
+~~~
+
+Arguments:
+
+Argument | Description
+---------------------|-----------------------
+return | return value type (id, number), id is the default
+field | field for the lookup (id, driver, name, longname, mixername, components)
+regex | regex string for the field match
+
+#### Find device substitution
+
+Usage example:
+
+~~~{.html}
+${find-device:type=pcm,field=name,regex='DMIC'}
+~~~
+
+Arguments:
+
+Argument | Description
+---------------------|-----------------------
+type | device type (pcm)
+stream | stream type (playback, capture), playback is default
+field | field for the lookup (id, name, subname)
+regex | regex string for the field match
+
+
+### Variable defines
+
+The variables can be defined and altered with the *Define* or *DefineRegex* blocks.
+The *Define* block looks like:
+
+~~~{.html}
+Define {
+ variable1 "a"
+ variable2 "b"
+}
+~~~
+
+The *DefineRegex* allows substring extraction like:
+
+~~~{.html}
+DefineRegex.rval {
+ Regex "(hello)|(regex)"
+ String "hello, it's my regex"
+}
+~~~
+
+The result will be stored to variables *rval1* as *hello* and *rval2* as *regex* (every matched
+substrings are stored to a separate variable with the sequence number postfix.
+
+Variables can be substituted using the `${var:rval1}` reference for example.
+
+### Conditions
+
+The configuration tree evaluation supports the conditions - *If* blocks. Each *If* blocks
+must define a *Condition* block and *True* or *False* blocks or both. The *True* or *False*
+blocks will be merged to the parent tree (where the *If* block is defined) when
+the *Condition* is evaluated.
+
+Example:
+
+~~~{.html}
+If.uniqueid {
+ Condition {
+ Type String
+ Haystack "abcd"
+ Needle "a"
+ }
+ True {
+ Define.a a
+ define.b b
+ }
+}
+~~~
+
+#### True (Type AlwaysTrue)
+
+Execute only *True* block. It may be used to change the evaluation order as
+explained in the *Configuration Tree* paragraph.
+
+#### String is empty (Type String)
+
+Field | Description
+---------------------|-----------------------
+Empty | string
+
+#### Strings are equal (Type String)
+
+Field | Description
+---------------------|-----------------------
+String1 | string
+String2 | substring in string
+
+#### Substring is present (Type String)
+
+Field | Description
+---------------------|-----------------------
+Haystack | string
+Needle | substring in string
+
+#### Regex match (Type RegexMatch)
+
+Field | Description
+---------------------|-----------------------
+String | string
+Regex | regex expression (extended posix, ignore case)
+
+#### ALSA control element exists (Type ControlExists)
+
+Field | Description
+---------------------|-----------------------
+Device | ALSA control device (see snd_ctl_open())
+Control | control in ASCII (parsed using snd_ctl_ascii_elem_id_parse())
+ControlEnum | value for the enum control (optional)
+
+Example:
+
+~~~{.html}
+If.fmic {
+ Condition {
+ Type ControlExists
+ Control "name='Front Mic Playback Switch'"
+ }
+ True {
+ ...
+ }
+}
+~~~
+
+
+*/
+
+/**
+ \}
+ */