]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Configuration:
authorJaroslav Kysela <perex@perex.cz>
Mon, 19 Nov 2001 08:14:21 +0000 (08:14 +0000)
committerJaroslav Kysela <perex@perex.cz>
Mon, 19 Nov 2001 08:14:21 +0000 (08:14 +0000)
  - changed snd_config_get_id function to follow semantic of other get functions
  - added snd_config_test_id
  - added runtime pointer type (not persistent)
    - added snd_config_make_pointer, snd_config_set_pointer, snd_config_get_pointer
  - added type/contents checking for callback functions
    - changed 'void *private_data' to 'snd_config_t *private_data'
  - renamed card_strtype functions to card_driver
Control:
  - fixed passing parameters to snd_ctl_async
Async handlers:
  - added public snd_async_handler_get_signo function
Documentation:
  - moved all documentation to source files

52 files changed:
aserver/aserver.c
doc/conf.doxygen [deleted file]
doc/confarg.doxygen [deleted file]
doc/conffunc.doxygen [deleted file]
doc/doxygen.cfg
doc/pcm.doxygen [deleted file]
include/conf.h
include/control.h
include/global.h
include/local.h
include/pcm.h
src/async.c
src/conf.c
src/conf/pcm/center_lfe.conf
src/conf/pcm/front.conf
src/conf/pcm/iec958.conf
src/conf/pcm/rear.conf
src/conf/pcm/surround40.conf
src/conf/pcm/surround51.conf
src/confmisc.c
src/control/control.c
src/control/control_hw.c
src/control/control_shm.c
src/control/setup.c
src/dlmisc.c
src/hwdep/hwdep.c
src/hwdep/hwdep_hw.c
src/pcm/pcm.c
src/pcm/pcm_adpcm.c
src/pcm/pcm_alaw.c
src/pcm/pcm_copy.c
src/pcm/pcm_file.c
src/pcm/pcm_hooks.c
src/pcm/pcm_hw.c
src/pcm/pcm_linear.c
src/pcm/pcm_meter.c
src/pcm/pcm_mulaw.c
src/pcm/pcm_multi.c
src/pcm/pcm_null.c
src/pcm/pcm_plug.c
src/pcm/pcm_rate.c
src/pcm/pcm_route.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c
src/rawmidi/rawmidi.c
src/rawmidi/rawmidi_hw.c
src/seq/seq.c
src/seq/seq_hw.c
src/timer/timer.c
src/timer/timer_hw.c
src/timer/timer_query.c
src/timer/timer_query_hw.c

index 6fccb8a20061ede674a6837efe1e3472b02b00c8..bc516afa9883201b283bce81972afc23851b7037 100644 (file)
@@ -1032,7 +1032,9 @@ int main(int argc, char **argv)
        }
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "host") == 0) {
diff --git a/doc/conf.doxygen b/doc/conf.doxygen
deleted file mode 100644 (file)
index 8c835c2..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*! \page conf Configuration files
-
-<P>Configuration files are using a simple format allowing the modern
-data description like nesting and array assignments.</P>
-
-\section conf_whitespace Whitespace
-
-Whitespace is the collective name given to spaces (blanks), horizontal and
-vertical tabs, newline characters, and comments. Whitespace can serve to
-indicate where configuration tokens start and end, but beyond this function,
-any surplus whitespace is discarded. For example, the two sequences
-
-\code
-  a 1 b 2
-\endcode
-
-and
-
-\code
-  a 1 
-     b 2
-\endcode
-
-are lexically equivalent and parse identically to give the four tokens:
-
-\code
-a
-1
-b
-2
-\endcode
-
-The ASCII characters representing whitespace can occur within literal
-strings, int which case they are protected from the normal parsing process
-(tey remain as part of the string). For example:
-
-\code
-  name "John Smith"
-\endcode
-
-parses to two tokens, including the single literal-string token "John
-Smith".
-
-\section conf_linesplicing Line splicing with \
-
-A special case occurs, if the final newline character encountered is
-preceded by a backslash (\) in the string value definition. The backslash
-and new line are both discarded, allowing two physical lines of text to be
-treated as one unit.
-
-\code
-"John \
-Smith"
-\endcode
-
-is parsed as "John Smith".
-
-\section conf_comments Comments
-
-A single-line comments are defined using character #. The comment can start
-in any position, and extends until the next new line.
-
-\code
-  a 1  # this is a comment
-\endcode
-
-\section conf_include Include another configuration file
-
-A new configuration file can be included using <filename> syntax. The global
-configuration directory can be referenced using <confdir:filename> syntax.
-
-\code
-</etc/alsa1.conf>
-<confdir:pcm/surround.conf>
-\endcode
-
-\section conf_punctuators Punctuators
-
-The configuration punctuators (also known as separators) are:
-
-\code
-  {} [] , ; = . ' " new-line form-feed carriage-return whitespace
-\endcode
-
-\subsection conf_braces Braces
-
-Open and close braces { } indicate the start and end of a compound
-statement:
-
-\code
-a {
-  b 1
-}
-\endcode
-
-\subsection conf_brackets Brackets
-
-Open and close brackets indicate single array definition. The identificators
-are automatically generated starting with zero.
-
-\code
-a [
-  "first"
-  "second"
-]
-\endcode
-
-Above code is equal to
-
-\code
-a.0 "first"
-a.1 "second"
-\endcode
-
-\subsection conf_comma_semicolon Comma and semicolon
-
-The comma (,) or semicolon (;) can separate the value assignments. It is not
-strictly required to use these separators, because any whitespace supplies
-them.
-
-\code
-a 1;
-b 1,
-\endcode
-
-\subsection conf_equal Equal sign
-
-The equal sign (=) separates can separate variable declarations from
-initialization lists:
-
-\code
-a=1
-b=2
-\endcode
-
-Using the equal signs is not required, because any whitespace supplies
-them.
-
-\section conf_assigns Assigns
-
-The configuration file defines id (key) and value pairs. The id (key) can be
-composed from any ASCII digits or chars from a to z or A to Z, including
-char _. The value can be either a string, integer or real number.
-
-\subsection conf_single Single assign
-
-\code
-a 1    # is equal to
-a=1    # is equal to
-a=1;   # is equal to
-a 1,
-\endcode
-
-\subsection conf_compound Compound assign (definition using braces)
-
-\code
-a {
-  b = 1
-}
-a={
-  b 1,
-}
-\endcode
-
-\section conf_compound1 Compound assign (one key definition)
-
-\code
-a.b 1
-a.b=1
-\endcode
-
-\subsection conf_array Array assign (definition using brackets)
-
-\code
-a [
-  "first"
-  "second"
-]
-\endcode
-
-\subsection conf_array1 Array assign (one key definition)
-
-\code
-a.0 "first"
-a.1 "second"
-\endcode
-
-\section conf_summary Summary
-
-\code
-# Configuration file syntax
-
-# Include a new configuration file
-<filename>
-
-# Simple assign
-name [=] value [,|;]
-
-# Compound assign (first style)
-name [=] {
-        name1 [=] value [,|;]
-        ...
-}
-
-# Compound assign (second style)
-name.name1 [=] value [,|;]
-
-# Array assign (first style)
-name [
-        value0 [,|;]
-        value1 [,|;]
-        ...
-]
-
-# Array assign (second style)
-name.0 [=] value0 [,|;]
-name.1 [=] value1 [,|;]
-\endcode
-
-*/
diff --git a/doc/confarg.doxygen b/doc/confarg.doxygen
deleted file mode 100644 (file)
index baccd0d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*! \page confarg Configuration - runtime arguments
-
-<P>The ALSA library can accept runtime arguments for some configuration
-blocks. This extension is on top of the basic syntax of the configuration
-files.<P>
-
-\section confarg_define Defining arguments
-
-Arguments are specified by id (key) @args and array values containing
-the string names of arguments:
-
-\code
-@args [ CARD ] # or
-@args.0 CARD
-\endcode
-
-\section confarg_type Defining argument type and default value
-
-Arguments type is specified by id (key) @args and argument name. The type
-and default value is specified in the compound:
-
-\code
-@args.CARD {
-  type string
-  default "abcd"
-}
-\endcode
-
-\section confarg_refer Refering argument
-
-Arguments are refered by dollar-sign ($) and name of argument:
-
-\code
-  card $CARD
-\endcode
-
-\section confarg_example Example
-
-\code
-pcm.demo {
-       @args [ CARD DEVICE ]
-       @args.CARD {
-               type string
-               default "supersonic"
-       }
-       @args.DEVICE {
-               type integer
-               default 0
-       }
-       type hw
-       card $CARD
-       device $DEVICE
-}
-\endcode
-
-*/
diff --git a/doc/conffunc.doxygen b/doc/conffunc.doxygen
deleted file mode 100644 (file)
index 7d5dfc1..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*! \page conffunc Configuration - runtime functions
-
-<P>The ALSA library accepts the runtime modification of configuration.
-The several build-in functions are available.</P>
-
-<P>The function is refered using id @func and function name. All other
-values in the current compound are used as configuration for the function.
-If compound func.<function_name> is defined in the root leafs, then library
-and function from this compound configuration is used, otherwise the prefix
-'snd_func_' is added to string and the code from the ALSA library is used.
-The definition of function looks like:</P> 
-
-\code
-func.remove_first_char {
-       lib "/usr/lib/libasoundextend.so"
-       func "extend_remove_first_char"
-}
-\endcode
-
-\section conffunc_getenv The getenv function
-
-The getenv function allows to get an environment value. The vars values
-(array) defined the order and names for the environment values. When the
-first environment value is found, then the function replaces the whole
-compound by this result. If no value is found, then the default value is
-used, if defined.
-
-\code
-       card {
-               @func getenv
-               vars [ MY_CARD CARD C ]
-               default 0
-       }
-\endcode
-
-\section conffunc_igetenv The igetenv function
-
-This function is same as getenv function, but the result value is converted
-to integer.
-
-\section conffunc_concat The concat function
-
-The concat function merges all given string in the array named string into
-one.
-
-\code
-       filename {
-               @func concat
-               strings [
-                       "/usr/share"
-                       "/sound"
-                       "/a.wav"
-               ]
-       }
-\endcode
-
-\section conffunc_datadir The datadir function
-
-This function return the configuration data directory (usually /usr/share/alsa)
-as string as result. This function requires no other values.
-
-
-\section conffunc_refer The refer function
-
-This function substitutes the current compound with the compound named (key
-name, value string) and filename (key file - optional, value string).
-
-\code
-       {
-               @func refer
-               file /etc/my-alsa.conf
-               name pcm.lastone
-       }
-\endcode
-
-\section conffunc_card_strtype The card_strtype function
-
-This function converts the given card number (key card, value integer) to card type
-(string).
-
-\section conffunc_card_id The card_id function
-
-This function returns the card id string for the given card number (key card, value
-integer).
-
-\section conffunc_pcm_id The pcm_id function
-
-This function returns the pcm id string for the given PCM device (key card,
-value integer; key device, value integer; key subdevice (optional), value
-integer).
-
-\section conffunc_private_string The private_string function
-
-This function returns the private data as string as result.
-
-\section conffunc_private_card_strtype The private_card_strtype function
-
-This function converts the private data (int) with card number to card type
-(string).
-
-\section conffunc_private_pcm_subdevice The private_pcm_subdevice function
-
-This functions returns the subdevice number for the pcm handle specified by
-the private data.
-
-*/
index 0f79e71c2518251335d2f21bbc749bec2db5fe5b..99c3cb0f7847b01db58a7321dc14ff5ea4a64223 100644 (file)
@@ -5,8 +5,7 @@ GENERATE_MAN     = NO
 GENERATE_RTF    = NO
 
 CASE_SENSE_NAMES = NO
-INPUT            = index.doxygen conf.doxygen confarg.doxygen \
-                  conffunc.doxygen pcm.doxygen \
+INPUT            = index.doxygen \
                   ../include/asoundlib.h \
                   ../include/version.h \
                   ../include/global.h \
diff --git a/doc/pcm.doxygen b/doc/pcm.doxygen
deleted file mode 100644 (file)
index 568408f..0000000
+++ /dev/null
@@ -1,441 +0,0 @@
-/*! \page pcm PCM (digital audio) interface
-
-<P>Although abbreviation PCM stands for Pulse Code Modulation, we are
-understanding it as general digital audio processing with volume samples
-generated in continuous time periods.</P>
-
-<P>Digital audio is the most commonly used method of representing
-sound inside a computer. In this method sound is stored as a sequence of
-samples taken from the audio signal using constant time intervals. 
-A sample represents volume of the signal at the moment when it
-was measured. In uncompressed digital audio each sample require one
-or more bytes of storage. The number of bytes required depends on number
-of channels (mono, stereo) and sample format (8 or 16 bits, mu-Law, etc.).
-The length of this interval determines the sampling rate. Commonly used
-sampling rates are between 8kHz (telephone quality) and
-48kHz (DAT tapes).</P>
-
-<P>The physical devices used in digital audio are called the
-ADC (Analog to Digital Converter) and DAC (Digital to Analog Converter).
-A device containing both ADC and DAC is commonly known as a codec. 
-The codec device used in a Sound Blaster cards is called a DSP which
-is somewhat misleading since DSP also stands for Digital Signal Processor
-(the SB DSP chip is very limited when compared to "true" DSP chips).</P>
-
-<P>Sampling parameters affect the quality of sound which can be
-reproduced from the recorded signal. The most fundamental parameter
-is sampling rate which limits the highest frequency that can be stored.
-It is well known (Nyquist's Sampling Theorem) that the highest frequency
-that can be stored in a sampled signal is at most 1/2 of the sampling
-frequency. For example, an 8 kHz sampling rate permits the recording of
-a signal in which the highest frequency is less than 4 kHz. Higher frequency
-signals must be filtered out before feeding them to ADC.</P>
-
-<P>Sample encoding limits the dynamic range of a recorded signal
-(difference between the faintest and the loudest signal that can be
-recorded). In theory the maximum dynamic range of signal is number_of_bits *
-6dB. This means that 8 bits sampling resolution gives dynamic range of
-48dB and 16 bit resolution gives 96dB.</P>
-
-<P>Quality has price. The number of bytes required to store an audio
-sequence depends on sampling rate, number of channels and sampling
-resolution. For example just 8000 bytes of memory is required to store
-one second of sound using 8kHz/8 bits/mono but 48kHz/16bit/stereo takes
-192 kilobytes. A 64 kbps ISDN channel is required to transfer a
-8kHz/8bit/mono audio stream in real time, and about 1.5Mbps is required
-for DAT quality (48kHz/16bit/stereo). On the other hand it is possible
-to store just 5.46 seconds of sound in a megabyte of memory when using
-48kHz/16bit/stereo sampling. With 8kHz/8bits/mono it is possible to store
-131 seconds of sound using the same amount of memory. It is possible
-to reduce memory and communication costs by compressing the recorded
-signal but this is beyond the scope of this document. </P>
-
-\section pcm_general_overview General overview
-
-ALSA uses the ring buffer to store outgoing (playback) and incoming (capture,
-record) samples. There are two pointers being mantained to allow
-a precise communication between application and device pointing to current
-processed sample by hardware and last processed sample by application.
-The modern audio chips allow to program the transfer time periods.
-It means that the stream of samples is divided to small chunks. Device
-acknowledges to application when the transfer of a chunk is complete.
-
-\section pcm_transfer Transfer methods in unix environments
-
-In the unix environment, data chunk acknowledges are received via standard I/O
-calls or event waiting routines (poll or select function). To accomplish
-this list, the asynchronous notification of acknowledges should be listed
-here. The ALSA implementation for these methods is described in
-the \ref alsa_transfers section.
-
-\subsection pcm_transfer_io Standard I/O transfers
-
-The standard I/O transfers are using the read (see 'man 2 read') and write
-(see 'man 2 write') C functions. There are two basic behaviours of these
-functions - blocked and non-blocked (see the O_NONBLOCK flag for the
-standard C open function - see 'man 2 open'). In non-blocked behaviour,
-these I/O functions never stops, they return -EAGAIN error code, when no
-data can be transferred (the ring buffer is full in our case). In blocked
-behaviour, these I/O functions stop and wait until there is a room in the
-ring buffer (playback) or until there are a new samples (capture). The ALSA
-implementation can be found in the \ref alsa_pcm_rw section.
-
-\subsection pcm_transfer_event Event waiting routines
-
-The poll or select functions (see 'man 2 poll' or 'man 2 select' for further
-details) allows to receive requests/events from the device while
-an application is waiting on events from other sources (like keyboard, screen,
-network etc.), too. The select function is old and deprecated in modern
-applications, so the ALSA library does not support it. The implemented
-transfer routines can be found in the \ref alsa_transfers section.
-
-\subsection pcm_transfer_async Asynchronous notification
-
-ALSA driver and library knows to handle the asynchronous notifications over
-the SIGIO signal. This signal allows to interrupt application and transfer
-data in the signal handler. For further details see the sigaction function
-('man 2 sigaction'). The section \ref pcm_async describes the ALSA API for
-this extension. The implemented transfer routines can be found in the
-\ref alsa_transfers section.
-
-\section pcm_open_behaviour Blocked and non-blocked open
-
-The ALSA PCM API uses a different behaviour when the device is opened
-with blocked or non-blocked mode. The mode can be specified with
-\a mode argument in \link ::snd_pcm_open() \endlink function.
-The blocked mode is the default (without \link ::SND_PCM_NONBLOCK \endlink mode).
-In this mode, the behaviour is that if the resources have already used
-with another application, then it blocks the caller, until resources are
-free. The non-blocked behaviour (with \link ::SND_PCM_NONBLOCK \endlink)
-doesn't block the caller in any way and returns -EBUSY error when the
-resources are not available. Note that the mode also determines the
-behaviour of standard I/O calls, returning -EAGAIN when non-blocked mode is
-used and the ring buffer is full (playback) or empty (capture).
-The operation mode for I/O calls can be changed later with
-the \link snd_pcm_nonblock() \endlink function.
-
-\section pcm_async Asynchronous mode
-
-There is also possibility to receive asynchronous notification after
-specified time periods. You may see the \link ::SND_PCM_ASYNC \endlink
-mode for \link ::snd_pcm_open() \endlink function and
-\link ::snd_async_add_pcm_handler() \endlink function for further details.
-
-\section pcm_handshake Handshake between application and library
-
-The ALSA PCM API design uses the states to determine the communication
-phase between application and library. The actual state can be determined
-using \link ::snd_pcm_state() \endlink call. There are these states:
-
-\par SND_PCM_STATE_OPEN
-The PCM device is in the open state. After the \link ::snd_pcm_open() \endlink open call,
-the device is in this state. Also, when \link ::snd_pcm_hw_params() \endlink call fails,
-then this state is entered to force application calling 
-\link ::snd_pcm_hw_params() \endlink function to set right communication
-parameters.
-
-\par SND_PCM_STATE_SETUP
-The PCM device has accepted communication parameters and it is waiting
-for \link ::snd_pcm_prepare() \endlink call to prepare the hardware for
-selected operation (playback or capture).
-
-\par SND_PCM_STATE_PREPARE
-The PCM device is prepared for operation. Application can use
-\link ::snd_pcm_start() \endlink call, write or read data to start
-the operation.
-
-\par SND_PCM_STATE_RUNNING
-The PCM device is running. It processes the samples. The stream can
-be stopped using the \link ::snd_pcm_drop() \endlink or
-\link ::snd_pcm_drain \endlink calls.
-
-\par SND_PCM_STATE_XRUN
-The PCM device reached overrun (capture) or underrun (playback).
-You can use the -EPIPE return code from I/O functions
-(\link ::snd_pcm_writei() \endlink, \link ::snd_pcm_writen() \endlink,
- \link ::snd_pcm_readi() \endlink, \link ::snd_pcm_readi() \endlink)
-to determine this state without checking
-the actual state via \link ::snd_pcm_state() \endlink call. You can recover from
-this state with \link ::snd_pcm_prepare() \endlink,
-\link ::snd_pcm_drop() \endlink or \link ::snd_pcm_drain() \endlink calls.
-
-\par SND_PCM_STATE_DRAINING
-The device is in this state when application using the capture mode
-called \link ::snd_pcm_drain() \endlink function. Until all data are
-read from the internal ring buffer using I/O routines
-(\link ::snd_pcm_readi() \endlink, \link ::snd_pcm_readn() \endlink),
-then the device stays in this state.
-
-\par SND_PCM_STATE_PAUSED
-The device is in this state when application called
-the \link ::snd_pcm_pause() \endlink function until the pause is released.
-Not all hardware supports this feature. Application should check the
-capability with the \link ::snd_pcm_hw_params_can_pause() \endlink.
-
-\par SND_PCM_STATE_SUSPENDED
-The device is in the suspend state provoked with the power management
-system. The stream can be resumed using \link ::snd_pcm_resume() \endlink
-call, but not all hardware supports this feature. Application should check
-the capability with the \link ::snd_pcm_hw_params_can_resume() \endlink.
-In other case, the calls \link ::snd_pcm_prepare() \endlink,
-\link ::snd_pcm_drop() \endlink, \link ::snd_pcm_drain() \endlink can be used
-to leave this state.
-
-\section pcm_formats PCM formats
-
-The full list of formats present the \link ::snd_pcm_format_t \endlink type.
-The 24-bit linear samples uses 32-bit physical space, but the sample is
-stored in low three bits. Some hardware does not support processing of full
-range, thus you may get the significative bits for linear samples via
-\link ::snd_pcm_hw_params_get_sbits \endlink function. The example: ICE1712
-chips support 32-bit sample processing, but low byte is ignored (playback)
-or zero (capture). The function \link ::snd_pcm_hw_params_get_sbits() \endlink
-returns 24 in the case.
-
-\section alsa_transfers ALSA transfers
-
-There are two methods to transfer samples in application. The first method
-is the standard read / write one. The second method, uses the direct audio
-buffer to communicate with the device while ALSA library manages this space
-itself. You can find examples of all communication schemes for playback
-in \ref example_test_pcm "Sine-wave generator example". To complete the
-list, we should note that \link ::snd_pcm_wait \endlink function contains
-embedded poll waiting implementation.
-
-\subsection alsa_pcm_rw Read / Write transfer
-
-There are two versions of read / write routines. The first expects the
-interleaved samples at input, and the second one expects non-interleaved
-(samples in separated buffers) at input. There are these functions for
-interleaved transfers: \link ::snd_pcm_writei \endlink,
-\link ::snd_pcm_readi \endlink. For non-interleaved transfers, there are
-these functions: \link ::snd_pcm_writen \endlink and \link ::snd_pcm_readn
-\endlink.
-
-\subsection alsa_mmap_rw Direct Read / Write transfer (via mmaped areas)
-
-There are two functions for this kind of transfer. Application can get an
-access to memory areas via \link ::snd_pcm_mmap_begin \endlink function.
-This functions returns the areas (single area is equal to a channel)
-containing the direct pointers to memory and sample position description
-in \link ::snd_pcm_channel_area_t \endlink structure. After application
-transfers the data in the memory areas, then it must be acknowledged
-the end of transfer via \link ::snd_pcm_mmap_commit() \endlink function
-to allow the ALSA library update the pointers to ring buffer. This sort of
-communication is also called "zero-copy", because the device does not require
-to copy the samples from application to another place in system memory.
-
-\par
-
-If you like to use the compatibility functions in mmap mode, there are
-read / write routines equaling to standard read / write transfers. Using
-these functions discards the benefits of direct access to memory region.
-See the \link ::snd_pcm_mmap_readi() \endlink,
-\link ::snd_pcm_writei() \endlink, \link ::snd_pcm_readn() \endlink
-and \link ::snd_pcm_writen() \endlink functions.
-
-\section pcm_params Managing parameters
-
-The ALSA PCM device uses two groups of PCM related parameters. The hardware
-parameters contains the stream description like format, rate, count of
-channels, ring buffer size etc. The software parameters contains the
-software (driver) related parameters. The communicatino behaviour can be
-controlled via these parameters, like automatic start, automatic stop,
-interrupting (chunk acknowledge) etc. The software parameters can be
-modified at any time (when valid hardware parameters are set). It includes
-the running state as well.
-
-\subsection pcm_hw_params Hardware related parameters
-
-The ALSA PCM devices use the parameter refining system for hardware
-parameters - \link ::snd_pcm_hw_params_t \endlink. It means, that
-application choose the full-range of configurations at first and then
-application sets single parameters until all parameters are elementary
-(definite).
-
-\par Access modes
-
-ALSA knows about five access modes. The first three can be used for direct
-communication. The access mode \link ::SND_PCM_ACCESS_MMAP_INTERLEAVED \endlink
-determines the direct memory area and interleaved sample organization.
-Interleaved organization means, that samples from channels are mixed together.
-The access mode \link ::SND_PCM_ACCESS_MMAP_NONINTERLEAVED \endlink
-determines the direct memory area and non-interleaved sample organization.
-Each channel has a separate buffer in the case. The complex direct memory
-organization represents the \link ::SND_PCM_ACCESS_MMAP_COMPLEX \endlink
-access mode. The sample organization does not fit the interleaved or
-non-interleaved access modes in the case. The last two access modes
-describes the read / write access methods.
-The \link ::SND_PCM_ACCESS_RW_INTERLEAVED \endlink access represents the read /
-write interleaved access and the \link ::SND_PCM_ACCESS_RW_NONINTERLEAVED \endlink
-represents the non-interleaved access.
-
-\par Formats
-
-The full list of formats is available in \link ::snd_pcm_format_t \endlink
-enumeration.
-
-\subsection pcm_sw_params Software related parameters
-
-These parameters - \link ::snd_pcm_sw_params_t \endlink can be modified at
-any time including the running state.
-
-\par Minimum available count of samples
-
-This parameter controls the wakeup point. If the count of available samples
-is equal or greater than this value, then application will be activated.
-
-\par Timestamp mode
-
-The timestamp mode specifies, if timestamps are activated. Currently, only
-\link ::SND_PCM_TSTAMP_NONE \endlink and \link ::SND_PCM_TSTAMP_MMAP
-\endlink modes are known. The mmap mode means that timestamp is taken
-on every period time boundary.
-
-\par Minimal sleep
-
-This parameters means the minimum of ticks to sleep using a standalone
-timer (usually the system timer). The tick resolution can be obtained
-via the function \link ::snd_pcm_hw_params_get_tick_time \endlink. This
-function can be used to fine-tune the transfer acknowledge process. It could
-be useful especially when some hardware does not support small transfer
-periods.
-
-\par Transfer align
-
-The read / write transfers can be aligned to this sample count. The modulo
-is ignored by device. Usually, this value is set to one (no align).
-
-\par Start threshold
-
-The start threshold parameter is used to determine the start point in
-stream. For playback, if samples in ring buffer is equal or greater than
-the start threshold parameters and the stream is not running, the stream will
-be started automatically from the device. For capture, if the application wants
-to read count of samples equal or greater then the stream will be started.
-If you want to use explicit start (\link ::snd_pcm_start \endlink), you can
-set this value greater than ring buffer size (in samples), but use the
-constant MAXINT is not a bad idea.
-
-\par Stop threshold
-
-Similarly, the stop threshold parameter is used to automatically stop
-the running stream, when the available samples crosses this boundary.
-It means, for playback, the empty samples in ring buffer and for capture,
-the filled (used) samples in ring buffer.
-
-\par Silence threshold
-
-The silence threshold specifies count of samples filled with silence
-ahead of the current application pointer for playback. It is useable
-for applications when an overrun is possible (like tasks depending on
-network I/O etc.). If application wants to manage the ahead samples itself,
-the \link ::snd_pcm_rewind() \endlink function allows to forget the last
-samples in the stream.
-
-\section pcm_status Obtaining device status
-
-The device status is stored in \link ::snd_pcm_status_t \endlink structure.
-These parameters can be obtained: the current stream state -
-\link ::snd_pcm_status_get_state \endlink, timestamp of trigger -
-\link ::snd_pcm_status_get_trigger_tstamp \endlink, timestamp of last
-update \link ::snd_pcm_status_get_tstamp \endlink, delay in samples -
-\link ::snd_pcm_status_get_delay \endlink, available count in samples -
-\link ::snd_pcm_status_get_avail \endlink, maximum available samples -
-\link ::snd_pcm_status_get_avail_max \endlink, ADC overrange count in
-samples - \link ::snd_pcm_status_get_overrange \endlink. The last two
-parameters - avail_max and overrange are reset to zero after the status
-call.
-
-\subsection pcm_status_fast Obtaining fast device status
-
-The function \link ::snd_pcm_avail_update \endlink updates the current
-available count of samples for writting (playback) or filled samples for
-reading (capture).
-<p>
-The function \link ::snd_pcm_delay \endlink returns the delay in samples.
-For playback, it means count of samples in the ring buffer before
-the next sample will be sent to DAC. For capture, it means count of samples
-in the ring buffer before the next sample will be captured from ADC.
-
-\section pcm_action Managing the stream state
-
-These functions directly and indirectly affecting the stream state:
-
-\par snd_pcm_hw_params
-The \link ::snd_pcm_hw_params \endlink function brings the stream state
-to \link ::SND_PCM_STATE_SETUP \endlink
-if successfully finishes, otherwise the state \link ::SND_PCM_STATE_OPEN
-\endlink is entered.
-
-\par snd_pcm_prepare
-The \link ::snd_pcm_prepare \endlink function enters the
-\link ::SND_PCM_STATE_PREPARED \endlink after a successfull finish.
-
-\par snd_pcm_start
-The \link ::snd_pcm_start \endlink function enters
-the \link ::SND_PCM_STATE_RUNNING \endlink after a successfull finish.
-
-\par snd_pcm_drop
-The \link ::snd_pcm_drop \endlink function enters the
-\link ::SND_PCM_STATE_SETUP \endlink state.
-
-\par snd_pcm_drain
-The \link ::snd_pcm_drain \endlink function enters the
-\link ::SND_PCM_STATE_DRAINING \endlink, if
-the capture device has some samples in the ring buffer otherwise
-\link ::SND_PCM_STATE_SETUP \endlink state is entered.
-
-\par snd_pcm_pause
-The \link ::snd_pcm_pause \endlink function enters the
-\link ::SND_PCM_STATE_PAUSED \endlink or
-\link ::SND_PCM_STATE_RUNNING \endlink.
-
-\par snd_pcm_writei, snd_pcm_writen
-The \link ::snd_pcm_writei \endlink and \link ::snd_pcm_writen \endlink
-functions can conditionally start the stream -
-\link ::SND_PCM_STATE_RUNNING \endlink. They depend on the start threshold
-software parameter.
-
-\par snd_pcm_readi, snd_pcm_readn
-The \link ::snd_pcm_readi \endlink and \link ::snd_pcm_readn \endlink
-functions can conditionally start the stream -
-\link ::SND_PCM_STATE_RUNNING \endlink. They depend on the start threshold
-software parameter.
-
-\section pcm_sync Streams synchronization
-
-There are two functions allowing link multiple streams together. In the
-case, the linking means that all operations are synchronized. Because the
-drivers cannot guarantee the synchronization (sample resolution) on hardware
-lacking this feature, the \link ::snd_pcm_info_get_sync \endlink function
-returns synchronization ID - \link ::snd_pcm_sync_id_t \endlink, which is equal
-for hardware synchronizated streams. When the \link ::snd_pcm_link \endlink
-function is called, all operations managing the stream state for these two
-streams are joined. The oposite function is \link ::snd_pcm_unlink \endlink.
-
-\section pcm_examples Examples
-
-The full featured examples with cross-links:
-
-\par Sine-wave generator
-\ref example_test_pcm "example code"
-\par
-This example shows various transfer methods for the playback direction.
-
-\par Latency measuring tool
-\ref example_test_latency "example code"
-\par
-This example shows the measuring of minimal latency between capture and
-playback devices.
-
-*/
-
-/**
- * \example ../test/pcm.c
- * \anchor example_test_pcm
- */
-/**
- * \example ../test/latency.c
- * \anchor example_test_latency
- */
index 74cfe113041153802a168b65a505141f100daa86..0fc0636b794d1ae7196884efd4908dcfc1af505a 100644 (file)
@@ -51,8 +51,10 @@ typedef enum _snd_config_type {
         SND_CONFIG_TYPE_REAL,
        /** Character string */
         SND_CONFIG_TYPE_STRING,
+        /** Pointer - runtime only - cannot be saved */
+        SND_CONFIG_TYPE_POINTER,
        /** Compound */
-       SND_CONFIG_TYPE_COMPOUND,
+       SND_CONFIG_TYPE_COMPOUND = 1024,
 } snd_config_type_t;
 
 /** Config node handle */
@@ -60,10 +62,13 @@ typedef struct _snd_config snd_config_t;
 /** Config compound iterator */
 typedef struct _snd_config_iterator *snd_config_iterator_t;
 
+extern snd_config_t *snd_config;
+
 int snd_config_top(snd_config_t **config);
 
 int snd_config_load(snd_config_t *config, snd_input_t *in);
 int snd_config_save(snd_config_t *config, snd_output_t *out);
+int snd_config_update(void);
 
 int snd_config_search(snd_config_t *config, const char *key,
                      snd_config_t **result);
@@ -74,10 +79,10 @@ int snd_config_search_definition(snd_config_t *config,
                                 snd_config_t **result);
 
 int snd_config_expand(snd_config_t *config, snd_config_t *root,
-                     const char *args, void *private_data,
+                     const char *args, snd_config_t *private_data,
                      snd_config_t **result);
 int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
-                       void *private_data, snd_config_t **result);
+                       snd_config_t *private_data, snd_config_t **result);
 
 int snd_config_add(snd_config_t *config, snd_config_t *leaf);
 int snd_config_delete(snd_config_t *config);
@@ -88,17 +93,24 @@ int snd_config_make(snd_config_t **config, const char *key,
 int snd_config_make_integer(snd_config_t **config, const char *key);
 int snd_config_make_real(snd_config_t **config, const char *key);
 int snd_config_make_string(snd_config_t **config, const char *key);
+int snd_config_make_pointer(snd_config_t **config, const char *key);
 int snd_config_make_compound(snd_config_t **config, const char *key, int join);
 
+snd_config_type_t snd_config_get_type(snd_config_t *config);
+
 int snd_config_set_id(snd_config_t *config, const char *id);
 int snd_config_set_integer(snd_config_t *config, long value);
 int snd_config_set_real(snd_config_t *config, double value);
 int snd_config_set_string(snd_config_t *config, const char *value);
 int snd_config_set_ascii(snd_config_t *config, const char *ascii);
+int snd_config_set_pointer(snd_config_t *config, const void *ptr);
+int snd_config_get_id(snd_config_t *config, const char **value);
 int snd_config_get_integer(snd_config_t *config, long *value);
 int snd_config_get_real(snd_config_t *config, double *value);
 int snd_config_get_string(snd_config_t *config, const char **value);
 int snd_config_get_ascii(snd_config_t *config, char **value);
+int snd_config_get_pointer(snd_config_t *config, const void **value);
+int snd_config_test_id(snd_config_t *config, const char *id);
 
 snd_config_iterator_t snd_config_iterator_first(snd_config_t *node);
 snd_config_iterator_t snd_config_iterator_next(snd_config_iterator_t iterator);
@@ -115,12 +127,6 @@ snd_config_t *snd_config_iterator_entry(snd_config_iterator_t iterator);
 #define snd_config_for_each(pos, next, node) \
        for (pos = snd_config_iterator_first(node), next = snd_config_iterator_next(pos); pos != snd_config_iterator_end(node); pos = next, next = snd_config_iterator_next(pos))
 
-snd_config_type_t snd_config_get_type(snd_config_t *config);
-const char *snd_config_get_id(snd_config_t *config);
-
-extern snd_config_t *snd_config;
-int snd_config_update(void);
-
 /* Misc functions */
 
 int snd_config_get_bool_ascii(const char *ascii);
index b13ed2546b8c6662bfad951825ccee3f215479ba..0c6ccc2110909bedeaaec8ace3c4b370f5860781 100644 (file)
@@ -192,12 +192,6 @@ int snd_card_get_index(const char *name);
 int snd_card_get_name(int card, char **name);
 int snd_card_get_longname(int card, char **name);
 
-int snd_sctl_build(snd_sctl_t **ctl, snd_ctl_t *handle, snd_config_t *config,
-                  void *private_data, int mode);
-int snd_sctl_free(snd_sctl_t *handle);
-int snd_sctl_install(snd_sctl_t *handle);
-int snd_sctl_remove(snd_sctl_t *handle);
-
 int snd_ctl_open(snd_ctl_t **ctl, const char *name, int mode);
 int snd_ctl_close(snd_ctl_t *ctl);
 int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock);
@@ -482,9 +476,23 @@ void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val);
 
 /** \} */
 
+/**
+ *  \defgroup SControl Setup Control Interface
+ *  \ingroup Control
+ *  The setup control interface - set or modify control elements from a configuration file.
+ *  \{
+ */
+
+int snd_sctl_build(snd_sctl_t **ctl, snd_ctl_t *handle, snd_config_t *config,
+                  snd_config_t *private_data, int mode);
+int snd_sctl_free(snd_sctl_t *handle);
+int snd_sctl_install(snd_sctl_t *handle);
+int snd_sctl_remove(snd_sctl_t *handle);
+
+/** \} */
+
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* __ALSA_CONTROL_H */
-
index cd72e552edd190f2511cd85c532674e73d2b583a..f4cb2700ef37fbfdf87ea9c0a28b752fcfadce5f 100644 (file)
 #define __ALSA_GLOBAL_H_
 
 /**
- *  \defgroup Global Global defines
- *  Global defines
+ *  \defgroup Global Global defines and functions
+ *  Global defines and functions.
  *  \{
  */
 
 #ifndef ATTRIBUTE_UNUSED
-#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) /**< don't print warning when attribute is not used */
+/** do not print warning (gcc) when function parameter is not used */
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
 #endif
 
 #ifdef PIC /* dynamic build */
@@ -88,9 +89,9 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd,
                          snd_async_callback_t callback, void *private_data);
 int snd_async_del_handler(snd_async_handler_t *handler);
 int snd_async_handler_get_fd(snd_async_handler_t *handler);
+int snd_async_handler_get_signo(snd_async_handler_t *handler);
 void *snd_async_handler_get_callback_private(snd_async_handler_t *handler);
 
 /** \} */
 
 #endif /* __ALSA_GLOBAL_H */
-
index ecff86ea5fb749d19b344c6e3aed66dc28c9a160..74f0ddc0d5d657a907d4e8f8c7d2bae8d25cb6e6 100644 (file)
@@ -113,8 +113,6 @@ typedef struct sndrv_seq_event snd_seq_event_t;
 #define SND_BIG_ENDIAN
 #endif
 
-extern int snd_async_signo;
-
 struct _snd_async_handler {
        enum {
                SND_ASYNC_HANDLER_GENERIC,
index 526a0ca8569eb6e06cb06049a73249a9375f1805..6ab6cef3babcb05894edf0a8b3400ee9e64473ef 100644 (file)
@@ -6,7 +6,8 @@
  * \author Takashi Iwai <tiwai@suse.de>
  * \date 1998-2001
  *
- * Application interface library for the ALSA driver
+ * Application interface library for the ALSA driver.
+ * See the \ref pcm page for more details.
  *
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -34,7 +35,7 @@ extern "C" {
 
 /**
  *  \defgroup PCM PCM Interface
- *  The PCM Interface.
+ *  See the \ref pcm page for more details.
  *  \{
  */
 
@@ -59,6 +60,7 @@ typedef struct _snd_pcm_subformat_mask snd_pcm_subformat_mask_t;
 /** PCM class */
 typedef enum _snd_pcm_class {
        /** standard device */
+
        SND_PCM_CLASS_GENERIC = 0,
        /** multichannel device */
        SND_PCM_CLASS_MULTI,
@@ -388,8 +390,8 @@ int snd_pcm_unlink(snd_pcm_t *pcm);
 
 /**
  * \defgroup PCM_Info Stream Information
- * PCM Stream Information
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -422,8 +424,8 @@ void snd_pcm_info_set_stream(snd_pcm_info_t *obj, snd_pcm_stream_t val);
 
 /**
  * \defgroup PCM_HW_Params Hardware Parameters
- * PCM Hardware Parameters
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -596,8 +598,8 @@ unsigned int snd_pcm_hw_params_set_tick_time_last(snd_pcm_t *pcm, snd_pcm_hw_par
 
 /**
  * \defgroup PCM_SW_Params Software Parameters
- * PCM Software Parameters
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -637,8 +639,8 @@ snd_pcm_uframes_t snd_pcm_sw_params_get_silence_size(const snd_pcm_sw_params_t *
 
 /**
  * \defgroup PCM_Access Access Mask Functions
- * PCM Access Mask Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -661,8 +663,8 @@ void snd_pcm_access_mask_reset(snd_pcm_access_mask_t *mask, snd_pcm_access_t val
 
 /**
  * \defgroup PCM_Format Format Mask Functions
- * PCM Format Mask Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -685,8 +687,8 @@ void snd_pcm_format_mask_reset(snd_pcm_format_mask_t *mask, snd_pcm_format_t val
 
 /**
  * \defgroup PCM_SubFormat Subformat Mask Functions
- * PCM Subformat Mask Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -709,8 +711,8 @@ void snd_pcm_subformat_mask_reset(snd_pcm_subformat_mask_t *mask, snd_pcm_subfor
 
 /**
  * \defgroup PCM_Status Status Functions
- * PCM Status Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -735,8 +737,8 @@ snd_pcm_uframes_t snd_pcm_status_get_overrange(const snd_pcm_status_t *obj);
 
 /**
  * \defgroup PCM_Description Description Functions
- * PCM Description Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -754,8 +756,8 @@ const char *snd_pcm_state_name(const snd_pcm_state_t state);
 
 /**
  * \defgroup PCM_Dump Debug Functions
- * PCM Debug Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -771,8 +773,8 @@ int snd_pcm_status_dump(snd_pcm_status_t *status, snd_output_t *out);
 
 /**
  * \defgroup PCM_Direct Direct Access (MMAP) Functions
- * PCM Direct Access (MMAP) Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -791,8 +793,8 @@ snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframe
 
 /**
  * \defgroup PCM_Helpers Helper Functions
- * PCM Helper Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -832,8 +834,8 @@ int snd_pcm_areas_copy(const snd_pcm_channel_area_t *dst_channels, snd_pcm_ufram
 
 /**
  * \defgroup PCM_Hook Hook Extension
- * PCM Hook Extension
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -861,8 +863,8 @@ int snd_pcm_hook_remove(snd_pcm_hook_t *hook);
 
 /**
  * \defgroup PCM_Scope Scope Plugin Extension
- * PCM Scope Plugin Extension
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -920,8 +922,8 @@ int16_t *snd_pcm_scope_s16_get_channel_buffer(snd_pcm_scope_t *scope,
 
 /**
  * \defgroup PCM_Deprecated Deprecated Functions
- * PCM Deprecated Functions
  * \ingroup PCM
+ * See the \ref pcm page for more details.
  * \{
  */
 
@@ -940,4 +942,3 @@ snd_pcm_xrun_t snd_pcm_sw_params_get_xrun_mode(const snd_pcm_sw_params_t *params
 #endif
 
 #endif /* __ALSA_PCM_H */
-
index aea46597ce676a56a25c8092c1bb1da2d2fb2284..a89bbfd3f39c44c3655a49b918c581ac9bf274cf 100644 (file)
@@ -30,7 +30,8 @@
 
 #ifdef SND_ASYNC_RT_SIGNAL
 /** async signal number */
-int snd_async_signo;
+static int snd_async_signo;
+
 void snd_async_init(void) __attribute__ ((constructor));
 
 void snd_async_init(void)
@@ -43,7 +44,7 @@ void snd_async_init(void)
 }
 #else
 /** async signal number */
-int snd_async_signo = SIGIO;
+static int snd_async_signo = SIGIO;
 #endif
 
 static LIST_HEAD(snd_async_handlers);
@@ -68,12 +69,18 @@ static void snd_async_handler(int signo ATTRIBUTE_UNUSED, siginfo_t *siginfo, vo
  * \param callback - Async callback
  * \param private_data - Private data for async callback
  * \result zero if success, otherwise a negative error code
+ *
+ * The function create the async handler. The ALSA extension
+ * for the standard SIGIO signal contains the multiplexer
+ * for multiple asynchronous notifiers using one sigaction
+ * callback.
  */
 int snd_async_add_handler(snd_async_handler_t **handler, int fd, 
                          snd_async_callback_t callback, void *private_data)
 {
        snd_async_handler_t *h;
        int was_empty;
+       assert(handler);
        h = malloc(sizeof(*h));
        if (!h)
                return -ENOMEM;
@@ -107,6 +114,7 @@ int snd_async_add_handler(snd_async_handler_t **handler, int fd,
 int snd_async_del_handler(snd_async_handler_t *handler)
 {
        int err = 0;
+       assert(handler);
        list_del(&handler->glist);
        if (list_empty(&snd_async_handlers)) {
                struct sigaction act;
@@ -139,6 +147,17 @@ int snd_async_del_handler(snd_async_handler_t *handler)
        return err;
 }
 
+/**
+ * \brief Get signal number assigned to async handler
+ * \param handler Async handler
+ * \result signal number if success, otherwise a negative error code
+ */
+int snd_async_handler_get_signo(snd_async_handler_t *handler)
+{
+       assert(handler);
+       return snd_async_signo;
+}
+
 /**
  * \brief Get file descriptor assigned to async handler
  * \param handler Async handler
@@ -146,6 +165,7 @@ int snd_async_del_handler(snd_async_handler_t *handler)
  */
 int snd_async_handler_get_fd(snd_async_handler_t *handler)
 {
+       assert(handler);
        return handler->fd;
 }
 
@@ -156,6 +176,7 @@ int snd_async_handler_get_fd(snd_async_handler_t *handler)
  */
 void *snd_async_handler_get_callback_private(snd_async_handler_t *handler)
 {
+       assert(handler);
        return handler->private_data;
 }
 
index 872001c2109d5834236ce671a993cf11d75e2581..4568c775d5743494fa229642a261335b1845ada1 100644 (file)
@@ -5,7 +5,7 @@
  * \author Jaroslav Kysela <perex@suse.cz>
  * \date 2000-2001
  *
- * Generic stdio-like input interface
+ * Tree based, full nesting configuration functions.
  */
 /*
  *  Configuration helper functions
  *
  */
 
+/*! \page conf Configuration files
+
+<P>Configuration files are using a simple format allowing the modern
+data description like nesting and array assignments.</P>
+
+\section conf_whitespace Whitespace
+
+Whitespace is the collective name given to spaces (blanks), horizontal and
+vertical tabs, newline characters, and comments. Whitespace can serve to
+indicate where configuration tokens start and end, but beyond this function,
+any surplus whitespace is discarded. For example, the two sequences
+
+\code
+  a 1 b 2
+\endcode
+
+and
+
+\code
+  a 1 
+     b 2
+\endcode
+
+are lexically equivalent and parse identically to give the four tokens:
+
+\code
+a
+1
+b
+2
+\endcode
+
+The ASCII characters representing whitespace can occur within literal
+strings, int which case they are protected from the normal parsing process
+(tey remain as part of the string). For example:
+
+\code
+  name "John Smith"
+\endcode
+
+parses to two tokens, including the single literal-string token "John
+Smith".
+
+\section conf_linesplicing Line splicing with \
+
+A special case occurs, if the final newline character encountered is
+preceded by a backslash (\) in the string value definition. The backslash
+and new line are both discarded, allowing two physical lines of text to be
+treated as one unit.
+
+\code
+"John \
+Smith"
+\endcode
+
+is parsed as "John Smith".
+
+\section conf_comments Comments
+
+A single-line comments are defined using character #. The comment can start
+in any position, and extends until the next new line.
+
+\code
+  a 1  # this is a comment
+\endcode
+
+\section conf_include Include another configuration file
+
+A new configuration file can be included using <filename> syntax. The global
+configuration directory can be referenced using <confdir:filename> syntax.
+
+\code
+</etc/alsa1.conf>
+<confdir:pcm/surround.conf>
+\endcode
+
+\section conf_punctuators Punctuators
+
+The configuration punctuators (also known as separators) are:
+
+\code
+  {} [] , ; = . ' " new-line form-feed carriage-return whitespace
+\endcode
+
+\subsection conf_braces Braces
+
+Open and close braces { } indicate the start and end of a compound
+statement:
+
+\code
+a {
+  b 1
+}
+\endcode
+
+\subsection conf_brackets Brackets
+
+Open and close brackets indicate single array definition. The identificators
+are automatically generated starting with zero.
+
+\code
+a [
+  "first"
+  "second"
+]
+\endcode
+
+Above code is equal to
+
+\code
+a.0 "first"
+a.1 "second"
+\endcode
+
+\subsection conf_comma_semicolon Comma and semicolon
+
+The comma (,) or semicolon (;) can separate the value assignments. It is not
+strictly required to use these separators, because any whitespace supplies
+them.
+
+\code
+a 1;
+b 1,
+\endcode
+
+\subsection conf_equal Equal sign
+
+The equal sign (=) separates can separate variable declarations from
+initialization lists:
+
+\code
+a=1
+b=2
+\endcode
+
+Using the equal signs is not required, because any whitespace supplies
+them.
+
+\section conf_assigns Assigns
+
+The configuration file defines id (key) and value pairs. The id (key) can be
+composed from any ASCII digits or chars from a to z or A to Z, including
+char _. The value can be either a string, integer or real number.
+
+\subsection conf_single Single assign
+
+\code
+a 1    # is equal to
+a=1    # is equal to
+a=1;   # is equal to
+a 1,
+\endcode
+
+\subsection conf_compound Compound assign (definition using braces)
+
+\code
+a {
+  b = 1
+}
+a={
+  b 1,
+}
+\endcode
+
+\section conf_compound1 Compound assign (one key definition)
+
+\code
+a.b 1
+a.b=1
+\endcode
+
+\subsection conf_array Array assign (definition using brackets)
+
+\code
+a [
+  "first"
+  "second"
+]
+\endcode
+
+\subsection conf_array1 Array assign (one key definition)
+
+\code
+a.0 "first"
+a.1 "second"
+\endcode
+
+\section conf_summary Summary
+
+\code
+# Configuration file syntax
+
+# Include a new configuration file
+<filename>
+
+# Simple assign
+name [=] value [,|;]
+
+# Compound assign (first style)
+name [=] {
+        name1 [=] value [,|;]
+        ...
+}
+
+# Compound assign (second style)
+name.name1 [=] value [,|;]
+
+# Array assign (first style)
+name [
+        value0 [,|;]
+        value1 [,|;]
+        ...
+]
+
+# Array assign (second style)
+name.0 [=] value0 [,|;]
+name.1 [=] value1 [,|;]
+\endcode
+
+*/
+
+/*! \page confarg Configuration - runtime arguments
+
+<P>The ALSA library can accept runtime arguments for some configuration
+blocks. This extension is on top of the basic syntax of the configuration
+files.<P>
+
+\section confarg_define Defining arguments
+
+Arguments are specified by id (key) @args and array values containing
+the string names of arguments:
+
+\code
+@args [ CARD ] # or
+@args.0 CARD
+\endcode
+
+\section confarg_type Defining argument type and default value
+
+Arguments type is specified by id (key) @args and argument name. The type
+and default value is specified in the compound:
+
+\code
+@args.CARD {
+  type string
+  default "abcd"
+}
+\endcode
+
+\section confarg_refer Refering argument
+
+Arguments are refered by dollar-sign ($) and name of argument:
+
+\code
+  card $CARD
+\endcode
+
+\section confarg_example Example
+
+\code
+pcm.demo {
+       @args [ CARD DEVICE ]
+       @args.CARD {
+               type string
+               default "supersonic"
+       }
+       @args.DEVICE {
+               type integer
+               default 0
+       }
+       type hw
+       card $CARD
+       device $DEVICE
+}
+\endcode
+
+*/
+
+/*! \page conffunc Configuration - runtime functions
+
+<P>The ALSA library accepts the runtime modification of configuration.
+The several build-in functions are available.</P>
+
+<P>The function is refered using id @func and function name. All other
+values in the current compound are used as configuration for the function.
+If compound func.<function_name> is defined in the root leafs, then library
+and function from this compound configuration is used, otherwise the prefix
+'snd_func_' is added to string and the code from the ALSA library is used.
+The definition of function looks like:</P> 
+
+\code
+func.remove_first_char {
+       lib "/usr/lib/libasoundextend.so"
+       func "extend_remove_first_char"
+}
+\endcode
+
+*/
+
+
 #include <stdarg.h>
 #include <wordexp.h>
 #include <dlfcn.h>
@@ -44,6 +344,7 @@ struct _snd_config {
                long integer;
                char *string;
                double real;
+               const void *ptr;
                struct {
                        struct list_head fields;
                        int join;
@@ -895,6 +1196,9 @@ static int _snd_config_save_leaf(snd_config_t *n, snd_output_t *out,
        case SND_CONFIG_TYPE_STRING:
                string_print(n->u.string, 0, out);
                break;
+       case SND_CONFIG_TYPE_POINTER:
+               SNDERR("cannot save runtime pointer type");
+               return -EINVAL;
        case SND_CONFIG_TYPE_COMPOUND:
                snd_output_putc(out, '{');
                snd_output_putc(out, '\n');
@@ -1024,11 +1328,14 @@ snd_config_type_t snd_config_get_type(snd_config_t *config)
 /**
  * \brief Return id of a config node
  * \param config Config node handle
- * \return node id
+ * \param value The result id
+ * \return 0 on success otherwise a negative error code
  */
-const char *snd_config_get_id(snd_config_t *config)
+int snd_config_get_id(snd_config_t *config, const char **id)
 {
-       return config->id;
+       assert(config && id);
+       *id = config->id;
+       return 0;
 }
 
 /**
@@ -1245,6 +1552,17 @@ int snd_config_make_string(snd_config_t **config, const char *id)
        return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
 }
 
+/**
+ * \brief Build a pointer config node
+ * \param config Returned config node handle pointer
+ * \param id Node id
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_config_make_pointer(snd_config_t **config, const char *id)
+{
+       return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
+}
+
 /**
  * \brief Build an empty compound config node
  * \param config Returned config node handle pointer
@@ -1312,6 +1630,21 @@ int snd_config_set_string(snd_config_t *config, const char *value)
        return 0;
 }
 
+/**
+ * \brief Change the value of a pointer config node
+ * \param config Config node handle
+ * \param ptr Value
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_config_set_pointer(snd_config_t *config, const void *value)
+{
+       assert(config);
+       if (config->type != SND_CONFIG_TYPE_POINTER)
+               return -EINVAL;
+       config->u.ptr = value;
+       return 0;
+}
+
 /**
  * \brief Change the value of a config node
  * \param config Config node handle
@@ -1399,6 +1732,21 @@ int snd_config_get_string(snd_config_t *config, const char **ptr)
        return 0;
 }
 
+/**
+ * \brief Get the value of a pointer config node
+ * \param config Config node handle
+ * \param ptr Returned value pointer
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_config_get_pointer(snd_config_t *config, const void **ptr)
+{
+       assert(config && ptr);
+       if (config->type != SND_CONFIG_TYPE_POINTER)
+               return -EINVAL;
+       *ptr = config->u.ptr;
+       return 0;
+}
+
 /**
  * \brief Get the value in ASCII form
  * \param config Config node handle
@@ -1453,6 +1801,18 @@ int snd_config_get_ascii(snd_config_t *config, char **ascii)
        return 0;
 }
 
+/**
+ * \brief Compare the config node id and given ASCII id
+ * \param config Config node handle
+ * \param id ASCII id
+ * \return the same value as result of the strcmp function
+ */
+int snd_config_test_id(snd_config_t *config, const char *id)
+{
+       assert(config && id);
+       return strcmp(config->id, id);
+}
+
 /**
  * \brief Dump a config tree contents
  * \param config Config node handle
@@ -1666,7 +2026,7 @@ int snd_config_search_alias(snd_config_t *config,
  */
 int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
 {
-       static int snd_config_hooks(snd_config_t *config, void *private_data);
+       static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
        SND_CONFIG_SEARCH(config, key, result, \
                                        err = snd_config_hooks(config, NULL); \
                                        if (err < 0) \
@@ -1683,7 +2043,7 @@ int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t
  */
 int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
 {
-       static int snd_config_hooks(snd_config_t *config, void *private_data);
+       static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
        SND_CONFIG_SEARCHA(root, config, key, result,
                                        snd_config_searcha_hooks,
                                        err = snd_config_hooks(config, NULL); \
@@ -1745,14 +2105,14 @@ static struct finfo {
 
 static unsigned int files_info_count = 0;
 
-static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, void *private_data)
+static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
 {
        void *h = NULL;
        snd_config_t *c, *func_conf = NULL;
        char *buf = NULL;
        const char *lib = NULL, *func_name = NULL;
        const char *str;
-       int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, void *private_data) = NULL;
+       int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL;
        int err;
 
        err = snd_config_search(config, "func", &c);
@@ -1774,7 +2134,7 @@ static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, void
                }
                snd_config_for_each(i, next, func_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id = n->id;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
@@ -1833,7 +2193,7 @@ static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, void
        return 0;
 }
 
-static int snd_config_hooks(snd_config_t *config, void *private_data)
+static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
 {
        snd_config_t *n;
        snd_config_iterator_t i, next;
@@ -1846,7 +2206,7 @@ static int snd_config_hooks(snd_config_t *config, void *private_data)
                hit = 0;
                snd_config_for_each(i, next, n) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id = n->id;
                        long i;
                        err = safe_strtol(id, &i);
                        if (err < 0) {
@@ -1877,7 +2237,7 @@ static int snd_config_hooks(snd_config_t *config, void *private_data)
  * \param private_data Private data
  * \return zero if success, otherwise a negative error code
  */
-int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, void *private_data)
+int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
 {
        snd_config_t *n, *res = NULL;
        snd_config_iterator_t i, next;
@@ -1913,7 +2273,7 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
                snd_config_t *c = snd_config_iterator_entry(i);
                const char *str;
                if ((err = snd_config_get_string(c, &str)) < 0) {
-                       SNDERR("Field %s is not a string", snd_config_get_id(c));
+                       SNDERR("Field %s is not a string", c->id);
                        goto _err;
                }
                fi_count++;
@@ -1927,7 +2287,7 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
                hit = 0;
                snd_config_for_each(i, next, n) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id = n->id;
                        long i;
                        err = safe_strtol(id, &i);
                        if (err < 0) {
@@ -2014,7 +2374,7 @@ int snd_determine_driver(int card, char **driver);
  * \param private_data Private data
  * \return zero if success, otherwise a negative error code
  */
-int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, snd_config_t **dst, void *private_data ATTRIBUTE_UNUSED)
+int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data ATTRIBUTE_UNUSED)
 {
        int card = -1, err;
        
@@ -2023,12 +2383,16 @@ int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config,
                if (err < 0)
                        return err;
                if (card >= 0) {
-                       snd_config_t *n;
+                       snd_config_t *n, *private_data = NULL;
                        const char *driver;
                        char *fdriver = NULL;
                        err = snd_determine_driver(card, &fdriver);
                        if (err < 0)
                                return err;
+                       err = snd_config_make_string(&private_data, "string");
+                       if (err < 0)
+                               goto __err;
+                       snd_config_set_string(private_data, fdriver);
                        if (snd_config_search(root, fdriver, &n) >= 0) {
                                if (snd_config_get_string(n, &driver) < 0)
                                        continue;
@@ -2043,7 +2407,10 @@ int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config,
                        } else {
                                driver = fdriver;
                        }
-                       err = snd_config_hook_load(root, config, &n, (void *)driver);
+                       err = snd_config_hook_load(root, config, &n, private_data);
+                     __err:
+                       if (private_data)
+                               snd_config_delete(private_data);
                        if (fdriver)
                                free(fdriver);
                        if (err < 0)
@@ -2255,14 +2622,14 @@ typedef int (*snd_config_walk_callback_t)(snd_config_t *src,
                                          snd_config_t *root,
                                          snd_config_t **dst,
                                          snd_config_walk_pass_t pass,
-                                         void *private_data);
+                                         snd_config_t *private_data);
 #endif
 
 static int snd_config_walk(snd_config_t *src,
                           snd_config_t *root,
                           snd_config_t **dst, 
                           snd_config_walk_callback_t callback,
-                          void *private_data)
+                          snd_config_t *private_data)
 {
        int err;
        snd_config_iterator_t i, next;
@@ -2303,10 +2670,10 @@ static int _snd_config_copy(snd_config_t *src,
                            snd_config_t *root ATTRIBUTE_UNUSED,
                            snd_config_t **dst,
                            snd_config_walk_pass_t pass,
-                           void *private_data ATTRIBUTE_UNUSED)
+                           snd_config_t *private_data ATTRIBUTE_UNUSED)
 {
        int err;
-       const char *id = snd_config_get_id(src);
+       const char *id = src->id;
        snd_config_type_t type = snd_config_get_type(src);
        switch (pass) {
        case SND_CONFIG_WALK_PASS_PRE:
@@ -2370,10 +2737,10 @@ static int _snd_config_expand(snd_config_t *src,
                              snd_config_t *root ATTRIBUTE_UNUSED,
                              snd_config_t **dst,
                              snd_config_walk_pass_t pass,
-                             void *private_data)
+                             snd_config_t *private_data)
 {
        int err;
-       const char *id = snd_config_get_id(src);
+       const char *id = src->id;
        snd_config_type_t type = snd_config_get_type(src);
        switch (pass) {
        case SND_CONFIG_WALK_PASS_PRE:
@@ -2453,7 +2820,7 @@ static int _snd_config_evaluate(snd_config_t *src,
                                snd_config_t *root,
                                snd_config_t **dst ATTRIBUTE_UNUSED,
                                snd_config_walk_pass_t pass,
-                               void *private_data)
+                               snd_config_t *private_data)
 {
        int err;
        if (pass == SND_CONFIG_WALK_PASS_PRE) {
@@ -2461,7 +2828,7 @@ static int _snd_config_evaluate(snd_config_t *src,
                const char *lib = NULL, *func_name = NULL;
                const char *str;
                int (*func)(snd_config_t **dst, snd_config_t *root,
-                           snd_config_t *src, void *private_data) = NULL;
+                           snd_config_t *src, snd_config_t *private_data) = NULL;
                void *h = NULL;
                snd_config_t *c, *func_conf = NULL;
                err = snd_config_search(src, "@func", &c);
@@ -2481,7 +2848,7 @@ static int _snd_config_evaluate(snd_config_t *src,
                        }
                        snd_config_for_each(i, next, func_conf) {
                                snd_config_t *n = snd_config_iterator_entry(i);
-                               const char *id = snd_config_get_id(n);
+                               const char *id = n->id;
                                if (strcmp(id, "comment") == 0)
                                        continue;
                                if (strcmp(id, "lib") == 0) {
@@ -2552,7 +2919,7 @@ static int _snd_config_evaluate(snd_config_t *src,
  * \return zero if success, otherwise a negative error code
  */
 int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
-                       void *private_data, snd_config_t **result)
+                       snd_config_t *private_data, snd_config_t **result)
 {
        /* FIXME: Only in place evaluation is currently implemented */
        assert(result == NULL);
@@ -2569,7 +2936,7 @@ static int load_defaults(snd_config_t *subs, snd_config_t *defs)
                        continue;
                snd_config_for_each(f, fnext, def) {
                        snd_config_t *fld = snd_config_iterator_entry(f);
-                       const char *id = snd_config_get_id(fld);
+                       const char *id = fld->id;
                        if (strcmp(id, "type") == 0)
                                continue;
                        if (strcmp(id, "default") == 0) {
@@ -2578,7 +2945,7 @@ static int load_defaults(snd_config_t *subs, snd_config_t *defs)
                                err = snd_config_copy(&deflt, fld);
                                if (err < 0)
                                        return err;
-                               err = snd_config_set_id(deflt, snd_config_get_id(def));
+                               err = snd_config_set_id(deflt, def->id);
                                if (err < 0) {
                                        snd_config_delete(deflt);
                                        return err;
@@ -2818,7 +3185,7 @@ static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
                snd_config_for_each(i, next, subs) {
                        snd_config_t *n = snd_config_iterator_entry(i);
                        snd_config_t *d;
-                       const char *id = snd_config_get_id(n);
+                       const char *id = n->id;
                        err = snd_config_search(defs, id, &d);
                        if (err < 0) {
                                SNDERR("Unknown parameter %s", id);
@@ -2856,7 +3223,7 @@ static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
                        err = -EINVAL;
                        goto _err;
                }
-               var = snd_config_get_id(def);
+               var = def->id;
                err = snd_config_search(subs, var, &sub);
                if (err >= 0)
                        snd_config_delete(sub);
@@ -2936,7 +3303,7 @@ static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
  * \return 0 on success otherwise a negative error code
  */
 int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args,
-                     void *private_data, snd_config_t **result)
+                     snd_config_t *private_data, snd_config_t **result)
 {
        int err;
        snd_config_t *defs, *subs = NULL, *res;
index 7ab08f712de372b25b159fd9be01057cac39c396..423f6cb4196b8e4bf2c75ee7c5d436af6a1976d9 100644 (file)
@@ -38,7 +38,7 @@ pcm.!center_lfe {
                strings [
                        "cards."
                        {
-                               @func card_strtype
+                               @func card_driver
                                card $CARD
                        }
                        ".pcm.center_lfe." $DEV ":CARD=" $CARD
index 73cad08a7aa740e2d09af090fa3fd47d82628fc7..74ba7f2e72c82e455577d20774952c6ee051b9ae 100644 (file)
@@ -38,7 +38,7 @@ pcm.!front {
                strings [
                        "cards."
                        {
-                               @func card_strtype
+                               @func card_driver
                                card $CARD
                        }
                        ".pcm.front." $DEV ":CARD=" $CARD
index 85c5bc114c139c2193405166c5a061984dfca805..555c58d51cbad8c9cb7530af2594166825ee8569 100644 (file)
@@ -58,7 +58,7 @@ pcm.!iec958 {
                strings [
                        "cards."
                        {
-                               @func card_strtype
+                               @func card_driver
                                card $CARD
                        }
                        ".pcm.iec958." $DEV ":"
index 85ad8ec4bfb1e2483f13f02d263564a4cb872fb7..33b4b90fe0b583c4bfcc2ce8ba5a9316b1374211 100644 (file)
@@ -38,7 +38,7 @@ pcm.!rear {
                strings [
                        "cards."
                        {
-                               @func card_strtype
+                               @func card_driver
                                card $CARD
                        }
                        ".pcm.rear." $DEV ":CARD=" $CARD
index 3368af77cc2d3eeb1a3abb81cd50ea7a61b1927f..a3b577aad7d3613adf54e6dc26679b837575ba41 100644 (file)
@@ -43,7 +43,7 @@ pcm.!surround40 {
                strings [
                        "cards."
                        {
-                               @func card_strtype
+                               @func card_driver
                                card $CARD
                        }
                        ".pcm.surround40." $DEV ":CARD=" $CARD
index fc66f7a33c6c7ad3a9d7758f49280ab61787e1df..1347033f96470e82f2167261673f37346f651901 100644 (file)
@@ -45,7 +45,7 @@ pcm.!surround51 {
                strings [
                        "cards."
                        {
-                               @func card_strtype
+                               @func card_driver
                                card $CARD
                        }
                        ".pcm.surround51." $DEV ":CARD=" $CARD
index efdb0713da5239c47cb36122dc4c8ad7587ed14c..31c96156898a82974115d5c7e78ab3fdecc4d0c6 100644 (file)
@@ -1,3 +1,11 @@
+/**
+ * \file confmisc.c
+ * \brief Configuration helper functions
+ * \author Abramo Bagnara <abramo@alsa-project.org>
+ * \author Jaroslav Kysela <perex@suse.cz>
+ * \date 2000-2001
+ * 
+ * Configuration helper functions.
 /*
  *  Miscellaneous configuration helper functions
  *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>,
  *
  */
 
+/*! \page conffunc
+
+\section Function reference
+
+<UL>
+  <LI>The getenv function - snd_func_getenv() - allows to obtain
+      an environment value. The result is string.
+  <LI>The igetenv function - snd_func_igetenv() - allows to obtain
+      an environment value. The result is integer.
+  <LI>The concat function - snd_func_concat() - merges all specified
+      strings. The result is string.
+  <LI>The datadir function - snd_func_datadir() - returns the
+      data directory. The result is string.
+  <LI>The refer function - snd_func_refer() - copies the refered
+      configuration. The result is same as the refered node.
+  <LI>The card_driver function - snd_func_card_driver() - returns
+      the driver identification. The result is string.
+  <LI>The card_id function - snd_func_card_id() - returns
+      the card identification. The result is string.
+  <LI>The pcm_id function - snd_func_pcm_id() - returns
+      the pcm identification. The result is string.
+  <LI>The private_string - snd_func_private_string() - returns
+      string using private_data node.
+  <LI>The private_card_driver - snd_func_private_card_driver() -
+      returns the driver identification using private_data node.
+      The result is string.
+  <LI>The private_pcm_subdevice - snd_func_private_pcm_subdevice() -
+      returns the PCM subdevice number using the private_data node.
+      The result is string.
+</UL>
+
+*/
+
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -62,21 +104,24 @@ int snd_config_get_bool_ascii(const char *ascii)
 int snd_config_get_bool(snd_config_t *conf)
 {
        long v;
-       const char *str;
+       const char *str, *id;
        int err;
 
+       err = snd_config_get_id(conf, &id);
+       if (err < 0)
+               return err;
        err = snd_config_get_integer(conf, &v);
        if (err >= 0) {
                if (v < 0 || v > 1) {
                _invalid_value:
-                       SNDERR("Invalid value for %s", snd_config_get_id(conf));
+                       SNDERR("Invalid value for %s", id);
                        return -EINVAL;
                }
                return v;
        }
        err = snd_config_get_string(conf, &str);
        if (err < 0) {
-               SNDERR("Invalid type for %s", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return -EINVAL;
        }
        err = snd_config_get_bool_ascii(str);
@@ -116,20 +161,24 @@ int snd_config_get_ctl_iface_ascii(const char *ascii)
 int snd_config_get_ctl_iface(snd_config_t *conf)
 {
        long v;
-       const char *str;
+       const char *str, *id;
        int err;
+
+       err = snd_config_get_id(conf, &id);
+       if (err < 0)
+               return err;
        err = snd_config_get_integer(conf, &v);
        if (err >= 0) {
                if (v < 0 || v > SND_CTL_ELEM_IFACE_LAST) {
                _invalid_value:
-                       SNDERR("Invalid value for %s", snd_config_get_id(conf));
+                       SNDERR("Invalid value for %s", id);
                        return -EINVAL;
                }
                return v;
        }
        err = snd_config_get_string(conf, &str);
        if (err < 0) {
-               SNDERR("Invalid type for %s", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return -EINVAL;
        }
        err = snd_config_get_ctl_iface_ascii(str);
@@ -142,7 +191,25 @@ int snd_config_get_ctl_iface(snd_config_t *conf)
  *  Helper functions for the configuration file
  */
 
-int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
+/**
+ * \brief Get environment value
+ * \param dst The destination node (result type is string)
+ * \param root The root source node
+ * \param src The source node, with vars and default definition
+ * \param private_data The private_data node
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func getenv
+               vars [ MY_CARD CARD C ]
+               default 0
+       }
+\endcode
+ */ 
+int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
+                   snd_config_t *private_data)
 {
        snd_config_t *n, *d;
        snd_config_iterator_t i, next;
@@ -178,9 +245,10 @@ int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, v
                hit = 0;
                snd_config_for_each(i, next, n) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
-                       const char *ptr, *env;
+                       const char *id, *ptr, *env;
                        long i;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) {
                                SNDERR("field %s is not a string", id);
                                err = -EINVAL;
@@ -209,9 +277,13 @@ int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, v
       __ok:
        err = res == NULL ? -ENOMEM : 0;
        if (err >= 0) {
-               err = snd_config_make_string(dst, snd_config_get_id(src));
-               if (err >= 0)
-                       snd_config_set_string(*dst, res);
+               const char *id;
+               err = snd_config_get_id(src, &id);
+               if (err >= 0) {
+                       err = snd_config_make_string(dst, id);
+                       if (err >= 0)
+                               snd_config_set_string(*dst, res);
+               }
                free(res);
        }
       __error:
@@ -219,38 +291,80 @@ int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, v
                free(def);
        return err;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_getenv, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
-int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
+/**
+ * \brief Get integer environment value
+ * \param dst The destination node (result type is integer)
+ * \param root The root source node
+ * \param src The source node, with vars and default definition
+ * \param private_data The private_data node
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func getenv
+               vars [ MY_DEVICE DEVICE D ]
+               default 0
+       }
+\endcode
+ */ 
+int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
+                    snd_config_t *private_data)
 {
        snd_config_t *d;
-       const char *str;
+       const char *str, *id;
        int err;
        long v;
+
        err = snd_func_getenv(&d, root, src, private_data);
        if (err < 0)
                return err;
        err = snd_config_get_string(d, &str);
        if (err < 0)
-               goto _end;
+               return err;
        err = safe_strtol(str, &v);
        if (err < 0)
-               goto _end;
-       err = snd_config_make_integer(dst, snd_config_get_id(src));
+               return err;;
+       err = snd_config_get_id(src, &id);
        if (err < 0)
-               goto _end;
+               return err;
+       err = snd_config_make_integer(dst, id);
+       if (err < 0)
+               return err;
        snd_config_set_integer(*dst, v);
-       err = 0;
-
- _end:
-       return err;
+       return 0;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_igetenv, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
                
-int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
+/**
+ * \brief Merge given strings
+ * \param dst The destination node (result type is string)
+ * \param root The root source node
+ * \param src The source node, with strings definition
+ * \param private_data The private_data node
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example (result is string "a1b2c3" ]:
+\code
+       {
+               @func concat
+               strings [ "a1" "b2" "c3" ]
+               default 0
+       }
+\endcode
+ */ 
+int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
+                   snd_config_t *private_data)
 {
        snd_config_t *n;
        snd_config_iterator_t i, next;
+       const char *id;
        char *res = NULL, *tmp;
        int idx = 0, len = 0, len1, err, hit;
        
@@ -269,8 +383,10 @@ int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src, v
                snd_config_for_each(i, next, n) {
                        snd_config_t *n = snd_config_iterator_entry(i);
                        char *ptr;
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
                        long i;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        err = safe_strtol(id, &i);
                        if (err < 0) {
                                SNDERR("id of field %s is not an integer", id);
@@ -303,24 +419,52 @@ int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src, v
                err = -EINVAL;
                goto __error;
        }
-       err = snd_config_make_string(dst, snd_config_get_id(src));
-       if (err >= 0)
-               snd_config_set_string(*dst, res);
+       err = snd_config_get_id(src, &id);
+       if (err >= 0) {
+               err = snd_config_make_string(dst, id);
+               if (err >= 0)
+                       snd_config_set_string(*dst, res);
+       }
        free(res);
       __error:
        return err;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_concat, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
+/**
+ * \brief Get data directory
+ * \param dst The destination node (result type is string)
+ * \param root The root source node
+ * \param src The source node
+ * \param private_data The private_data node (unused)
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example (result is "/usr/share/alsa" using default paths):
+\code
+       {
+               @func datadir
+       }
+\endcode
+ */ 
 int snd_func_datadir(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
-                    snd_config_t *src, void *private_data ATTRIBUTE_UNUSED)
+                    snd_config_t *src, snd_config_t *private_data ATTRIBUTE_UNUSED)
 {
-       int err = snd_config_make_string(dst, snd_config_get_id(src));
+       int err;
+       const char *id;
+       
+       err = snd_config_get_id(src, &id);
+       if (err < 0)
+               return err;
+       err = snd_config_make_string(dst, id);
        if (err >= 0)
                err = snd_config_set_string(*dst, DATADIR "/alsa");
-       return 0;
+       return err;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_datadir, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
 static int open_ctl(long card, snd_ctl_t **ctl)
 {
@@ -344,19 +488,53 @@ static int string_from_integer(char **dst, long v)
 }
 #endif
 
-int snd_func_private_string(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *src, void *private_data)
+/**
+ * \brief Get string from private_data
+ * \param dst The destination node (result type is string)
+ * \param root The root source node
+ * \param src The source node
+ * \param private_data The private_data node (type string, id == "string")
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func private_string
+       }
+\endcode
+ */ 
+int snd_func_private_string(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
+                           snd_config_t *src, snd_config_t *private_data)
 {
        int err;
+       snd_config_t *n;
+       const char *str, *id;
 
        if (private_data == NULL)
                return snd_config_copy(dst, src);
-       err = snd_config_make_string(dst, snd_config_get_id(src));
-       if (err >= 0)
-               err = snd_config_set_string(*dst, (char *)private_data);
+       err = snd_config_test_id(private_data, "string");
+       if (err) {
+               SNDERR("field string not found");
+               return -EINVAL;
+       }
+       err = snd_config_get_string(private_data, &str);
+       if (err < 0) {
+               SNDERR("field string is not a string");
+               return err;
+       }
+       err = snd_config_get_id(src, &id);
+       if (err >= 0) {
+               err = snd_config_make_string(dst, id);
+               if (err >= 0)
+                       err = snd_config_set_string(*dst, str);
+       }
        return err;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_private_string, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
+#ifndef DOC_HIDDEN
 int snd_determine_driver(int card, char **driver)
 {
        snd_ctl_t *ctl = NULL;
@@ -388,25 +566,77 @@ int snd_determine_driver(int card, char **driver)
                snd_ctl_close(ctl);
        return err;
 }
+#endif
 
-int snd_func_private_card_strtype(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *src, void *private_data)
+/**
+ * \brief Get driver identification using private_data
+ * \param dst The destination node (result type is string)
+ * \param root The root source node
+ * \param src The source node
+ * \param private_data The private_data node (type = integer, id = "card")
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func private_card_driver
+       }
+\endcode
+ */ 
+int snd_func_private_card_driver(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *src,
+                                snd_config_t *private_data)
 {
        char *driver;
+       snd_config_t *n;
+       const char *id;
        int err;
+       long card;
 
-       if ((err = snd_determine_driver((long)private_data, &driver)) < 0)
+       err = snd_config_test_id(private_data, "card");
+       if (err) {
+               SNDERR("field card not found");
+               return -EINVAL;
+       }
+       err = snd_config_get_integer(n, &card);
+       if (err < 0) {
+               SNDERR("field card is not an integer");
                return err;
-       err = snd_config_make_string(dst, snd_config_get_id(src));
-       if (err >= 0)
-               err = snd_config_set_string(*dst, driver);
+       }
+       if ((err = snd_determine_driver(card, &driver)) < 0)
+               return err;
+       err = snd_config_get_id(src, &id);
+       if (err >= 0) {
+               err = snd_config_make_string(dst, id);
+               if (err >= 0)
+                       err = snd_config_set_string(*dst, driver);
+       }
        free(driver);
        return err;
 }
-SND_DLSYM_BUILD_VERSION(snd_func_private_card_strtype, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#ifndef DOC_HIDDEN
+SND_DLSYM_BUILD_VERSION(snd_func_private_card_driver, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
-int snd_func_card_strtype(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
+/**
+ * \brief Get driver identification
+ * \param dst The destination node (result type is string)
+ * \param root The root source node
+ * \param src The source node
+ * \param private_data The private_data node
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func card_driver
+               card 0
+       }
+\endcode
+ */ 
+int snd_func_card_driver(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
+                        snd_config_t *private_data)
 {
-       snd_config_t *n;
+       snd_config_t *n, *val;
        char *str;
        long v;
        int err;
@@ -433,16 +663,42 @@ int snd_func_card_strtype(snd_config_t **dst, snd_config_t *root, snd_config_t *
                return v;
        }
        free(str);
-       return snd_func_private_card_strtype(dst, root, src, (void *)v);
+       err = snd_config_make_integer(&val, "card");
+       if (err < 0)
+               return err;
+       snd_config_set_integer(val, v);
+       err = snd_func_private_card_driver(dst, root, src, val);
+       snd_config_delete(val);
+       return err;
 }
-SND_DLSYM_BUILD_VERSION(snd_func_card_strtype, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#ifndef DOC_HIDDEN
+SND_DLSYM_BUILD_VERSION(snd_func_card_driver, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
-int snd_func_card_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
+/**
+ * \brief Get card identification
+ * \param dst The destination node (result type is string)
+ * \param root The root source node
+ * \param src The source node
+ * \param private_data The private_data node
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func card_id
+               card 0
+       }
+\endcode
+ */ 
+int snd_func_card_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
+                    snd_config_t *private_data)
 {
        snd_config_t *n;
        char *res = NULL;
        snd_ctl_t *ctl = NULL;
        snd_ctl_card_info_t *info;
+       const char *id;
        long v;
        int err;
        
@@ -477,22 +733,46 @@ int snd_func_card_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
                err = -ENOMEM;
                goto __error;
        }
-       err = snd_config_make_string(dst, snd_config_get_id(src));
-       if (err >= 0)
-               err = snd_config_set_string(*dst, res);
+       err = snd_config_get_id(src, &id);
+       if (err >= 0) {
+               err = snd_config_make_string(dst, id);
+               if (err >= 0)
+                       err = snd_config_set_string(*dst, res);
+       }
        free(res);
       __error:
        if (ctl)
                snd_ctl_close(ctl);
        return err;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_card_id, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
+/**
+ * \brief Get pcm identification
+ * \param dst The destination node (result type is string)
+ * \param root The root source node
+ * \param src The source node
+ * \param private_data The private_data node
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func pcm_id
+               card 0
+               device 0
+               subdevice 0     # optional
+       }
+\endcode
+ */ 
 int snd_func_pcm_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
 {
        snd_config_t *n;
        snd_ctl_t *ctl = NULL;
        snd_pcm_info_t *info;
+       const char *id;
        long card, device, subdevice = 0;
        int err;
        
@@ -551,42 +831,94 @@ int snd_func_pcm_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src, v
                SNDERR("snd_ctl_pcm_info error: %s", snd_strerror(err));
                goto __error;
        }
-       err = snd_config_make_string(dst, snd_config_get_id(src));
-       if (err >= 0)
-               err = snd_config_set_string(*dst, snd_pcm_info_get_id(info));
+       err = snd_config_get_id(src, &id);
+       if (err >= 0) {
+               err = snd_config_make_string(dst, id);
+               if (err >= 0)
+                       err = snd_config_set_string(*dst, snd_pcm_info_get_id(info));
+       }
       __error:
        if (ctl)
                snd_ctl_close(ctl);
        return err;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_pcm_id, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
-int snd_func_private_pcm_subdevice(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *src, void *private_data)
+/**
+ * \brief Get pcm subdevice using private_data
+ * \param dst The destination node (result type is integer)
+ * \param root The root source node
+ * \param src The source node
+ * \param private_data The private_data node (type = pointer, id = "pcm_handle")
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func private_pcm_subdevice
+       }
+\endcode
+ */ 
+int snd_func_private_pcm_subdevice(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
+                                  snd_config_t *src, snd_config_t *private_data)
 {
-       char *res = NULL;
        snd_pcm_info_t *info;
+       snd_config_t *n;
+       const char *id;
+       snd_pcm_t *pcm;
        int err;
 
        if (private_data == NULL)
                return snd_config_copy(dst, src);
+       err = snd_config_test_id(private_data, "pcm_handle");
+       if (err) {
+               SNDERR("field pcm_handle not found");
+               return -EINVAL;
+       }
+       err = snd_config_get_pointer(private_data, (const void **)&pcm);
+       if (err < 0) {
+               SNDERR("field pcm_handle is not a pointer");
+               return err;
+       }
        snd_pcm_info_alloca(&info);
-       err = snd_pcm_info((snd_pcm_t *)private_data, info);
+       err = snd_pcm_info(pcm, info);
        if (err < 0) {
                SNDERR("snd_ctl_pcm_info error: %s", snd_strerror(err));
                return err;
        }
-       res = strdup(snd_pcm_info_get_id(info));
-       if (res == NULL)
-               return -ENOMEM;
-       err = snd_config_make_integer(dst, snd_config_get_id(src));
-       if (err >= 0)
-               err = snd_config_set_integer(*dst, snd_pcm_info_get_subdevice(info));
-       free(res);
+       err = snd_config_get_id(src, &id);
+       if (err >= 0) {
+               err = snd_config_make_integer(dst, id);
+               if (err >= 0)
+                       err = snd_config_set_integer(*dst, snd_pcm_info_get_subdevice(info));
+       }
        return err;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_private_pcm_subdevice, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
 
-int snd_func_refer(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
+/**
+ * \brief Copy the refered configuration node
+ * \param dst The destination node (result type is same as refered node)
+ * \param root The root source node (can be modified!!!)
+ * \param src The source node
+ * \param private_data The private_data node
+ * \return a positive value when success otherwise a negative error number
+ *
+ * Example:
+\code
+       {
+               @func refer
+               file "/etc/myconf.conf"         # optional
+               name "id1.id2.id3"
+       }
+\endcode
+ */ 
+int snd_func_refer(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
+                  snd_config_t *private_data)
 {
        snd_config_t *n;
        const char *file = NULL, *name = NULL;
@@ -631,17 +963,21 @@ int snd_func_refer(snd_config_t **dst, snd_config_t *root, snd_config_t *src, vo
                        goto _end;
                }
                err = snd_config_load(root, input);
-               if (err < 0) {
-                       snd_input_close(input);
+               snd_input_close(input);
+               if (err < 0)
                        goto _end;
-               }
        }
        err = snd_config_search_definition(root, NULL, name, dst);
-       if (err >= 0)
-               err = snd_config_set_id(*dst, snd_config_get_id(src));
-       else
+       if (err >= 0) {
+               const char *id;
+               err = snd_config_get_id(src, &id);
+               if (err >= 0)
+                       err = snd_config_set_id(*dst, id);
+       } else
                SNDERR("Unable to find definition '%s'", name);
  _end:
        return err;
 }
+#ifndef DOC_HIDDEN
 SND_DLSYM_BUILD_VERSION(snd_func_refer, SND_CONFIG_DLSYM_VERSION_EVALUATE);
+#endif
index 029a860fa76c71e3444a0d3d59305980e746dd9a..5a04d1d0e86a365af40f9c7a03444b4afbc327ee 100644 (file)
@@ -444,7 +444,7 @@ int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl,
        was_empty = list_empty(&ctl->async_handlers);
        list_add_tail(&h->hlist, &ctl->async_handlers);
        if (was_empty) {
-               err = snd_ctl_async(ctl, getpid(), snd_async_signo);
+               err = snd_ctl_async(ctl, snd_async_get_signo(h), getpid());
                if (err < 0) {
                        snd_async_del_handler(h);
                        return err;
@@ -474,6 +474,7 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
        snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
        const char *lib = NULL, *open_name = NULL;
+       const char *id;
        int (*open_func)(snd_ctl_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL;
 #ifndef PIC
        extern void *snd_control_open_symbols(void);
@@ -491,9 +492,14 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
                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", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return err;
        }
        err = snd_config_search_definition(ctl_root, "ctl_type", str, &type_conf);
@@ -504,7 +510,9 @@ static int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
                }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
index e9b147c5d79449cc95f770ea4ced389b7de7bfec..7cf62a2ca052118720931c07b766d3b7ac5adb9d 100644 (file)
@@ -349,7 +349,9 @@ int _snd_ctl_hw_open(snd_ctl_t **handlep, char *name, snd_config_t *root ATTRIBU
        int err;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "type") == 0)
index 24b416e615e35b092c80ee3c608cdf07132dcfe5..99df087b6717d757796b277fb4e911c1363808f0 100644 (file)
@@ -572,7 +572,9 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd_c
        struct hostent *h;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "type") == 0)
@@ -617,7 +619,9 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd_c
        }
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "host") == 0) {
index f2d0d778e3090e98dbe880865ffedb207159d6b9..88b46f603967d2d147570665b5792f773fc0583b 100644 (file)
@@ -335,7 +335,10 @@ static int snd_config_get_ctl_elem_value(snd_config_t *conf,
 
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               err = safe_strtol(snd_config_get_id(n), &idx);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
+               err = safe_strtol(id, &idx);
                if (err < 0 || idx < 0 || (unsigned int) idx >= count) {
                        SNDERR("bad value index");
                        return -EINVAL;
@@ -381,7 +384,7 @@ static int snd_config_get_ctl_elem_value(snd_config_t *conf,
        return 0;
 }
 
-static int add_elem(snd_sctl_t *h, snd_config_t *_conf, void *private_data)
+static int add_elem(snd_sctl_t *h, snd_config_t *_conf, snd_config_t *private_data)
 {
        snd_config_t *conf;
        snd_config_iterator_t i, next;
@@ -401,7 +404,9 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, void *private_data)
                return err;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) {
@@ -576,7 +581,7 @@ static int add_elem(snd_sctl_t *h, snd_config_t *_conf, void *private_data)
  * \param mode Build mode - SND_SCTL_xxxx
  * \result zero if success, otherwise a negative error code
  */
-int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, void *private_data, int mode)
+int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, snd_config_t *private_data, int mode)
 {
        snd_sctl_t *h;
        snd_config_iterator_t i, next;
index 4fd497b0578d125817c8f8ad449675f444d5b05a..138ccc01c0186b5ab68731ddbc8a0f4fb725750d 100644 (file)
@@ -41,6 +41,9 @@ struct snd_dlsym_link *snd_dlsym_start = NULL;
  * \param name name, similar to dlopen
  * \param mode mode, similar to dlopen
  * \return pointer to handle
+ *
+ * The extension is a special code for the static build of
+ * the alsa-lib library.
  */
 void *snd_dlopen(const char *name, int mode)
 {
@@ -55,6 +58,9 @@ void *snd_dlopen(const char *name, int mode)
  * \brief Close the dynamic library, with ALSA extension
  * \param handle handle, similar to dlclose
  * \return zero if success, otherwise an error code
+ *
+ * The extension is a special code for the static build of
+ * the alsa-lib library.
  */
 int snd_dlclose(void *handle)
 {
@@ -80,6 +86,8 @@ static int snd_dlsym_verify(void *handle, const char *name, const char *version)
        if (handle == NULL)
                return -EINVAL;
        vname = alloca(1 + strlen(name) + strlen(version) + 1);
+       if (vname == NULL)
+               return -ENOMEM;
        vname[0] = '_';
        strcpy(vname + 1, name);
        strcat(vname, version);
@@ -89,11 +97,16 @@ static int snd_dlsym_verify(void *handle, const char *name, const char *version)
                SNDERR("unable to verify version for symbol %s", name);
        return res;
 }
+
 /**
  * \brief Resolve the symbol, with ALSA extension
  * \param handle handle, similar to dlsym
  * \param name symbol name
  * \param version symbol version
+ *
+ * This special version of dlsym function checks also
+ * the version of symbol. The version of a symbol should
+ * be defined using #SND_DLSYM_BUILD_VERSION macro.
  */
 void *snd_dlsym(void *handle, const char *name, const char *version)
 {
@@ -101,8 +114,8 @@ void *snd_dlsym(void *handle, const char *name, const char *version)
 
 #ifndef PIC
        if (handle == &snd_dlsym_start) {
-               /* it's the funny part, we are looking for a symbol */
-               /* in a static library */
+               /* it's the funny part: */
+               /* we are looking for a symbol in a static library */
                struct snd_dlsym_link *link = snd_dlsym_start;
                while (link) {
                        if (!strcmp(name, link->dlsym_name))
index 5180de95b61706f6479c564c99b260ba895ddd47..23dbf6a98352d4bce3a3e5ad63db49d42253708d 100644 (file)
@@ -46,6 +46,7 @@ static int snd_hwdep_open_conf(snd_hwdep_t **hwdep,
        int err;
        snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
+       const char *id;
        const char *lib = NULL, *open_name = NULL;
        int (*open_func)(snd_hwdep_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL;
 #ifndef PIC
@@ -64,9 +65,14 @@ static int snd_hwdep_open_conf(snd_hwdep_t **hwdep,
                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", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return err;
        }
        err = snd_config_search_definition(hwdep_root, "hwdep_type", str, &type_conf);
@@ -77,7 +83,9 @@ static int snd_hwdep_open_conf(snd_hwdep_t **hwdep,
                }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
index 63ea4d6dd552407ee1dc364a145a27f40dd26bac..b9f4625dc1caff1e6378a21c40a3a0acd8114bcf 100644 (file)
@@ -152,7 +152,9 @@ int _snd_hwdep_hw_open(snd_hwdep_t **hwdep, char *name,
        int err;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "type") == 0)
index 615660ea7f4edc635d9814e3bd409d4ac1d07949..4e397e1a88f933e86050c50efa9a1bd2e24f3788 100644 (file)
@@ -1,5 +1,6 @@
 /**
  * \file pcm/pcm.c
+ * \ingroup PCM
  * \brief PCM Interface
  * \author Jaroslav Kysela <perex@suse.cz>
  * \author Abramo Bagnara <abramo@alsa-project.org>
@@ -11,6 +12,8 @@
  * 44100 you'll hear 44100 frames per second. The size in bytes of a
  * frame may be obtained from bits needed to store a sample and
  * channels count.
+ *
+ * See the \ref pcm page for more details.
  */
 /*
  *  PCM Interface - main file
  *
  */
 
+/*! \page pcm PCM (digital audio) interface
+
+<P>Although abbreviation PCM stands for Pulse Code Modulation, we are
+understanding it as general digital audio processing with volume samples
+generated in continuous time periods.</P>
+
+<P>Digital audio is the most commonly used method of representing
+sound inside a computer. In this method sound is stored as a sequence of
+samples taken from the audio signal using constant time intervals. 
+A sample represents volume of the signal at the moment when it
+was measured. In uncompressed digital audio each sample require one
+or more bytes of storage. The number of bytes required depends on number
+of channels (mono, stereo) and sample format (8 or 16 bits, mu-Law, etc.).
+The length of this interval determines the sampling rate. Commonly used
+sampling rates are between 8kHz (telephone quality) and
+48kHz (DAT tapes).</P>
+
+<P>The physical devices used in digital audio are called the
+ADC (Analog to Digital Converter) and DAC (Digital to Analog Converter).
+A device containing both ADC and DAC is commonly known as a codec. 
+The codec device used in a Sound Blaster cards is called a DSP which
+is somewhat misleading since DSP also stands for Digital Signal Processor
+(the SB DSP chip is very limited when compared to "true" DSP chips).</P>
+
+<P>Sampling parameters affect the quality of sound which can be
+reproduced from the recorded signal. The most fundamental parameter
+is sampling rate which limits the highest frequency that can be stored.
+It is well known (Nyquist's Sampling Theorem) that the highest frequency
+that can be stored in a sampled signal is at most 1/2 of the sampling
+frequency. For example, an 8 kHz sampling rate permits the recording of
+a signal in which the highest frequency is less than 4 kHz. Higher frequency
+signals must be filtered out before feeding them to ADC.</P>
+
+<P>Sample encoding limits the dynamic range of a recorded signal
+(difference between the faintest and the loudest signal that can be
+recorded). In theory the maximum dynamic range of signal is number_of_bits *
+6dB. This means that 8 bits sampling resolution gives dynamic range of
+48dB and 16 bit resolution gives 96dB.</P>
+
+<P>Quality has price. The number of bytes required to store an audio
+sequence depends on sampling rate, number of channels and sampling
+resolution. For example just 8000 bytes of memory is required to store
+one second of sound using 8kHz/8 bits/mono but 48kHz/16bit/stereo takes
+192 kilobytes. A 64 kbps ISDN channel is required to transfer a
+8kHz/8bit/mono audio stream in real time, and about 1.5Mbps is required
+for DAT quality (48kHz/16bit/stereo). On the other hand it is possible
+to store just 5.46 seconds of sound in a megabyte of memory when using
+48kHz/16bit/stereo sampling. With 8kHz/8bits/mono it is possible to store
+131 seconds of sound using the same amount of memory. It is possible
+to reduce memory and communication costs by compressing the recorded
+signal but this is beyond the scope of this document. </P>
+
+\section pcm_general_overview General overview
+
+ALSA uses the ring buffer to store outgoing (playback) and incoming (capture,
+record) samples. There are two pointers being mantained to allow
+a precise communication between application and device pointing to current
+processed sample by hardware and last processed sample by application.
+The modern audio chips allow to program the transfer time periods.
+It means that the stream of samples is divided to small chunks. Device
+acknowledges to application when the transfer of a chunk is complete.
+
+\section pcm_transfer Transfer methods in unix environments
+
+In the unix environment, data chunk acknowledges are received via standard I/O
+calls or event waiting routines (poll or select function). To accomplish
+this list, the asynchronous notification of acknowledges should be listed
+here. The ALSA implementation for these methods is described in
+the \ref alsa_transfers section.
+
+\subsection pcm_transfer_io Standard I/O transfers
+
+The standard I/O transfers are using the read (see 'man 2 read') and write
+(see 'man 2 write') C functions. There are two basic behaviours of these
+functions - blocked and non-blocked (see the O_NONBLOCK flag for the
+standard C open function - see 'man 2 open'). In non-blocked behaviour,
+these I/O functions never stops, they return -EAGAIN error code, when no
+data can be transferred (the ring buffer is full in our case). In blocked
+behaviour, these I/O functions stop and wait until there is a room in the
+ring buffer (playback) or until there are a new samples (capture). The ALSA
+implementation can be found in the \ref alsa_pcm_rw section.
+
+\subsection pcm_transfer_event Event waiting routines
+
+The poll or select functions (see 'man 2 poll' or 'man 2 select' for further
+details) allows to receive requests/events from the device while
+an application is waiting on events from other sources (like keyboard, screen,
+network etc.), too. The select function is old and deprecated in modern
+applications, so the ALSA library does not support it. The implemented
+transfer routines can be found in the \ref alsa_transfers section.
+
+\subsection pcm_transfer_async Asynchronous notification
+
+ALSA driver and library knows to handle the asynchronous notifications over
+the SIGIO signal. This signal allows to interrupt application and transfer
+data in the signal handler. For further details see the sigaction function
+('man 2 sigaction'). The section \ref pcm_async describes the ALSA API for
+this extension. The implemented transfer routines can be found in the
+\ref alsa_transfers section.
+
+\section pcm_open_behaviour Blocked and non-blocked open
+
+The ALSA PCM API uses a different behaviour when the device is opened
+with blocked or non-blocked mode. The mode can be specified with
+\a mode argument in \link ::snd_pcm_open() \endlink function.
+The blocked mode is the default (without \link ::SND_PCM_NONBLOCK \endlink mode).
+In this mode, the behaviour is that if the resources have already used
+with another application, then it blocks the caller, until resources are
+free. The non-blocked behaviour (with \link ::SND_PCM_NONBLOCK \endlink)
+doesn't block the caller in any way and returns -EBUSY error when the
+resources are not available. Note that the mode also determines the
+behaviour of standard I/O calls, returning -EAGAIN when non-blocked mode is
+used and the ring buffer is full (playback) or empty (capture).
+The operation mode for I/O calls can be changed later with
+the \link snd_pcm_nonblock() \endlink function.
+
+\section pcm_async Asynchronous mode
+
+There is also possibility to receive asynchronous notification after
+specified time periods. You may see the \link ::SND_PCM_ASYNC \endlink
+mode for \link ::snd_pcm_open() \endlink function and
+\link ::snd_async_add_pcm_handler() \endlink function for further details.
+
+\section pcm_handshake Handshake between application and library
+
+The ALSA PCM API design uses the states to determine the communication
+phase between application and library. The actual state can be determined
+using \link ::snd_pcm_state() \endlink call. There are these states:
+
+\par SND_PCM_STATE_OPEN
+The PCM device is in the open state. After the \link ::snd_pcm_open() \endlink open call,
+the device is in this state. Also, when \link ::snd_pcm_hw_params() \endlink call fails,
+then this state is entered to force application calling 
+\link ::snd_pcm_hw_params() \endlink function to set right communication
+parameters.
+
+\par SND_PCM_STATE_SETUP
+The PCM device has accepted communication parameters and it is waiting
+for \link ::snd_pcm_prepare() \endlink call to prepare the hardware for
+selected operation (playback or capture).
+
+\par SND_PCM_STATE_PREPARE
+The PCM device is prepared for operation. Application can use
+\link ::snd_pcm_start() \endlink call, write or read data to start
+the operation.
+
+\par SND_PCM_STATE_RUNNING
+The PCM device is running. It processes the samples. The stream can
+be stopped using the \link ::snd_pcm_drop() \endlink or
+\link ::snd_pcm_drain \endlink calls.
+
+\par SND_PCM_STATE_XRUN
+The PCM device reached overrun (capture) or underrun (playback).
+You can use the -EPIPE return code from I/O functions
+(\link ::snd_pcm_writei() \endlink, \link ::snd_pcm_writen() \endlink,
+ \link ::snd_pcm_readi() \endlink, \link ::snd_pcm_readi() \endlink)
+to determine this state without checking
+the actual state via \link ::snd_pcm_state() \endlink call. You can recover from
+this state with \link ::snd_pcm_prepare() \endlink,
+\link ::snd_pcm_drop() \endlink or \link ::snd_pcm_drain() \endlink calls.
+
+\par SND_PCM_STATE_DRAINING
+The device is in this state when application using the capture mode
+called \link ::snd_pcm_drain() \endlink function. Until all data are
+read from the internal ring buffer using I/O routines
+(\link ::snd_pcm_readi() \endlink, \link ::snd_pcm_readn() \endlink),
+then the device stays in this state.
+
+\par SND_PCM_STATE_PAUSED
+The device is in this state when application called
+the \link ::snd_pcm_pause() \endlink function until the pause is released.
+Not all hardware supports this feature. Application should check the
+capability with the \link ::snd_pcm_hw_params_can_pause() \endlink.
+
+\par SND_PCM_STATE_SUSPENDED
+The device is in the suspend state provoked with the power management
+system. The stream can be resumed using \link ::snd_pcm_resume() \endlink
+call, but not all hardware supports this feature. Application should check
+the capability with the \link ::snd_pcm_hw_params_can_resume() \endlink.
+In other case, the calls \link ::snd_pcm_prepare() \endlink,
+\link ::snd_pcm_drop() \endlink, \link ::snd_pcm_drain() \endlink can be used
+to leave this state.
+
+\section pcm_formats PCM formats
+
+The full list of formats present the \link ::snd_pcm_format_t \endlink type.
+The 24-bit linear samples uses 32-bit physical space, but the sample is
+stored in low three bits. Some hardware does not support processing of full
+range, thus you may get the significative bits for linear samples via
+\link ::snd_pcm_hw_params_get_sbits \endlink function. The example: ICE1712
+chips support 32-bit sample processing, but low byte is ignored (playback)
+or zero (capture). The function \link ::snd_pcm_hw_params_get_sbits() \endlink
+returns 24 in the case.
+
+\section alsa_transfers ALSA transfers
+
+There are two methods to transfer samples in application. The first method
+is the standard read / write one. The second method, uses the direct audio
+buffer to communicate with the device while ALSA library manages this space
+itself. You can find examples of all communication schemes for playback
+in \ref example_test_pcm "Sine-wave generator example". To complete the
+list, we should note that \link ::snd_pcm_wait \endlink function contains
+embedded poll waiting implementation.
+
+\subsection alsa_pcm_rw Read / Write transfer
+
+There are two versions of read / write routines. The first expects the
+interleaved samples at input, and the second one expects non-interleaved
+(samples in separated buffers) at input. There are these functions for
+interleaved transfers: \link ::snd_pcm_writei \endlink,
+\link ::snd_pcm_readi \endlink. For non-interleaved transfers, there are
+these functions: \link ::snd_pcm_writen \endlink and \link ::snd_pcm_readn
+\endlink.
+
+\subsection alsa_mmap_rw Direct Read / Write transfer (via mmaped areas)
+
+There are two functions for this kind of transfer. Application can get an
+access to memory areas via \link ::snd_pcm_mmap_begin \endlink function.
+This functions returns the areas (single area is equal to a channel)
+containing the direct pointers to memory and sample position description
+in \link ::snd_pcm_channel_area_t \endlink structure. After application
+transfers the data in the memory areas, then it must be acknowledged
+the end of transfer via \link ::snd_pcm_mmap_commit() \endlink function
+to allow the ALSA library update the pointers to ring buffer. This sort of
+communication is also called "zero-copy", because the device does not require
+to copy the samples from application to another place in system memory.
+
+\par
+
+If you like to use the compatibility functions in mmap mode, there are
+read / write routines equaling to standard read / write transfers. Using
+these functions discards the benefits of direct access to memory region.
+See the \link ::snd_pcm_mmap_readi() \endlink,
+\link ::snd_pcm_writei() \endlink, \link ::snd_pcm_readn() \endlink
+and \link ::snd_pcm_writen() \endlink functions.
+
+\section pcm_params Managing parameters
+
+The ALSA PCM device uses two groups of PCM related parameters. The hardware
+parameters contains the stream description like format, rate, count of
+channels, ring buffer size etc. The software parameters contains the
+software (driver) related parameters. The communicatino behaviour can be
+controlled via these parameters, like automatic start, automatic stop,
+interrupting (chunk acknowledge) etc. The software parameters can be
+modified at any time (when valid hardware parameters are set). It includes
+the running state as well.
+
+\subsection pcm_hw_params Hardware related parameters
+
+The ALSA PCM devices use the parameter refining system for hardware
+parameters - \link ::snd_pcm_hw_params_t \endlink. It means, that
+application choose the full-range of configurations at first and then
+application sets single parameters until all parameters are elementary
+(definite).
+
+\par Access modes
+
+ALSA knows about five access modes. The first three can be used for direct
+communication. The access mode \link ::SND_PCM_ACCESS_MMAP_INTERLEAVED \endlink
+determines the direct memory area and interleaved sample organization.
+Interleaved organization means, that samples from channels are mixed together.
+The access mode \link ::SND_PCM_ACCESS_MMAP_NONINTERLEAVED \endlink
+determines the direct memory area and non-interleaved sample organization.
+Each channel has a separate buffer in the case. The complex direct memory
+organization represents the \link ::SND_PCM_ACCESS_MMAP_COMPLEX \endlink
+access mode. The sample organization does not fit the interleaved or
+non-interleaved access modes in the case. The last two access modes
+describes the read / write access methods.
+The \link ::SND_PCM_ACCESS_RW_INTERLEAVED \endlink access represents the read /
+write interleaved access and the \link ::SND_PCM_ACCESS_RW_NONINTERLEAVED \endlink
+represents the non-interleaved access.
+
+\par Formats
+
+The full list of formats is available in \link ::snd_pcm_format_t \endlink
+enumeration.
+
+\subsection pcm_sw_params Software related parameters
+
+These parameters - \link ::snd_pcm_sw_params_t \endlink can be modified at
+any time including the running state.
+
+\par Minimum available count of samples
+
+This parameter controls the wakeup point. If the count of available samples
+is equal or greater than this value, then application will be activated.
+
+\par Timestamp mode
+
+The timestamp mode specifies, if timestamps are activated. Currently, only
+\link ::SND_PCM_TSTAMP_NONE \endlink and \link ::SND_PCM_TSTAMP_MMAP
+\endlink modes are known. The mmap mode means that timestamp is taken
+on every period time boundary.
+
+\par Minimal sleep
+
+This parameters means the minimum of ticks to sleep using a standalone
+timer (usually the system timer). The tick resolution can be obtained
+via the function \link ::snd_pcm_hw_params_get_tick_time \endlink. This
+function can be used to fine-tune the transfer acknowledge process. It could
+be useful especially when some hardware does not support small transfer
+periods.
+
+\par Transfer align
+
+The read / write transfers can be aligned to this sample count. The modulo
+is ignored by device. Usually, this value is set to one (no align).
+
+\par Start threshold
+
+The start threshold parameter is used to determine the start point in
+stream. For playback, if samples in ring buffer is equal or greater than
+the start threshold parameters and the stream is not running, the stream will
+be started automatically from the device. For capture, if the application wants
+to read count of samples equal or greater then the stream will be started.
+If you want to use explicit start (\link ::snd_pcm_start \endlink), you can
+set this value greater than ring buffer size (in samples), but use the
+constant MAXINT is not a bad idea.
+
+\par Stop threshold
+
+Similarly, the stop threshold parameter is used to automatically stop
+the running stream, when the available samples crosses this boundary.
+It means, for playback, the empty samples in ring buffer and for capture,
+the filled (used) samples in ring buffer.
+
+\par Silence threshold
+
+The silence threshold specifies count of samples filled with silence
+ahead of the current application pointer for playback. It is useable
+for applications when an overrun is possible (like tasks depending on
+network I/O etc.). If application wants to manage the ahead samples itself,
+the \link ::snd_pcm_rewind() \endlink function allows to forget the last
+samples in the stream.
+
+\section pcm_status Obtaining device status
+
+The device status is stored in \link ::snd_pcm_status_t \endlink structure.
+These parameters can be obtained: the current stream state -
+\link ::snd_pcm_status_get_state \endlink, timestamp of trigger -
+\link ::snd_pcm_status_get_trigger_tstamp \endlink, timestamp of last
+update \link ::snd_pcm_status_get_tstamp \endlink, delay in samples -
+\link ::snd_pcm_status_get_delay \endlink, available count in samples -
+\link ::snd_pcm_status_get_avail \endlink, maximum available samples -
+\link ::snd_pcm_status_get_avail_max \endlink, ADC overrange count in
+samples - \link ::snd_pcm_status_get_overrange \endlink. The last two
+parameters - avail_max and overrange are reset to zero after the status
+call.
+
+\subsection pcm_status_fast Obtaining fast device status
+
+The function \link ::snd_pcm_avail_update \endlink updates the current
+available count of samples for writting (playback) or filled samples for
+reading (capture).
+<p>
+The function \link ::snd_pcm_delay \endlink returns the delay in samples.
+For playback, it means count of samples in the ring buffer before
+the next sample will be sent to DAC. For capture, it means count of samples
+in the ring buffer before the next sample will be captured from ADC.
+
+\section pcm_action Managing the stream state
+
+These functions directly and indirectly affecting the stream state:
+
+\par snd_pcm_hw_params
+The \link ::snd_pcm_hw_params \endlink function brings the stream state
+to \link ::SND_PCM_STATE_SETUP \endlink
+if successfully finishes, otherwise the state \link ::SND_PCM_STATE_OPEN
+\endlink is entered.
+
+\par snd_pcm_prepare
+The \link ::snd_pcm_prepare \endlink function enters the
+\link ::SND_PCM_STATE_PREPARED \endlink after a successfull finish.
+
+\par snd_pcm_start
+The \link ::snd_pcm_start \endlink function enters
+the \link ::SND_PCM_STATE_RUNNING \endlink after a successfull finish.
+
+\par snd_pcm_drop
+The \link ::snd_pcm_drop \endlink function enters the
+\link ::SND_PCM_STATE_SETUP \endlink state.
+
+\par snd_pcm_drain
+The \link ::snd_pcm_drain \endlink function enters the
+\link ::SND_PCM_STATE_DRAINING \endlink, if
+the capture device has some samples in the ring buffer otherwise
+\link ::SND_PCM_STATE_SETUP \endlink state is entered.
+
+\par snd_pcm_pause
+The \link ::snd_pcm_pause \endlink function enters the
+\link ::SND_PCM_STATE_PAUSED \endlink or
+\link ::SND_PCM_STATE_RUNNING \endlink.
+
+\par snd_pcm_writei, snd_pcm_writen
+The \link ::snd_pcm_writei \endlink and \link ::snd_pcm_writen \endlink
+functions can conditionally start the stream -
+\link ::SND_PCM_STATE_RUNNING \endlink. They depend on the start threshold
+software parameter.
+
+\par snd_pcm_readi, snd_pcm_readn
+The \link ::snd_pcm_readi \endlink and \link ::snd_pcm_readn \endlink
+functions can conditionally start the stream -
+\link ::SND_PCM_STATE_RUNNING \endlink. They depend on the start threshold
+software parameter.
+
+\section pcm_sync Streams synchronization
+
+There are two functions allowing link multiple streams together. In the
+case, the linking means that all operations are synchronized. Because the
+drivers cannot guarantee the synchronization (sample resolution) on hardware
+lacking this feature, the \link ::snd_pcm_info_get_sync \endlink function
+returns synchronization ID - \link ::snd_pcm_sync_id_t \endlink, which is equal
+for hardware synchronizated streams. When the \link ::snd_pcm_link \endlink
+function is called, all operations managing the stream state for these two
+streams are joined. The oposite function is \link ::snd_pcm_unlink \endlink.
+
+\section pcm_examples Examples
+
+The full featured examples with cross-links:
+
+\par Sine-wave generator
+\ref example_test_pcm "example code"
+\par
+This example shows various transfer methods for the playback direction.
+
+\par Latency measuring tool
+\ref example_test_latency "example code"
+\par
+This example shows the measuring of minimal latency between capture and
+playback devices.
+
+*/
+
+/**
+ * \example ../test/pcm.c
+ * \anchor example_test_pcm
+ */
+/**
+ * \example ../test/latency.c
+ * \anchor example_test_latency
+ */
+
+
 #include <stdio.h>
 #include <string.h>
 #include <malloc.h>
@@ -995,7 +1441,7 @@ int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm,
        was_empty = list_empty(&pcm->async_handlers);
        list_add_tail(&h->hlist, &pcm->async_handlers);
        if (was_empty) {
-               err = snd_pcm_async(pcm, snd_async_signo, getpid());
+               err = snd_pcm_async(pcm, snd_async_signo(h), getpid());
                if (err < 0) {
                        snd_async_del_handler(h);
                        return err;
@@ -1025,6 +1471,7 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
        int err;
        snd_config_t *conf, *type_conf = NULL;
        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 *, 
@@ -1045,9 +1492,14 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
                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", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return err;
        }
        err = snd_config_search_definition(pcm_root, "pcm_type", str, &type_conf);
@@ -1058,7 +1510,9 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
                }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
@@ -4645,7 +5099,9 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
        va_end(args);
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "pcm") == 0) {
index d21b263dfe41ecaf7d6ec3972d09ce653e57f5f9..cc7d99735e88002ac606e7ab1cf9f1ac01cddf50 100644 (file)
@@ -557,7 +557,9 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
        snd_pcm_format_t sformat;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index d11df70db19a5ff6b0a0cf2250bb0dace9c79ea1..aa61e76e3a3915cec7769c245fc658137cf318b6 100644 (file)
@@ -430,7 +430,9 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
        snd_pcm_format_t sformat;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index 3e02f03cbf2497d74f1b36714e5e597b75e77b7f..1e9287ed8776f0a8a82515b2ac837234348697d3 100644 (file)
@@ -199,7 +199,9 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name,
        snd_config_t *slave = NULL, *sconf;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index 525f35de0aef746e1eca01f49c14702b66168e0e..b65b7f1d63d551cd52cf6911d277e540ebafe9cf 100644 (file)
@@ -474,7 +474,9 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
        long fd = -1;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index 59a625bd26854bc283e63e92951c4f14b2b6b2a1..65cc3e964df229c04020bedaa3ee345ed6951095 100644 (file)
@@ -335,7 +335,7 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_
 {
        int err;
        char buf[256];
-       const char *str;
+       const char *str, *id;
        const char *lib = NULL, *install = NULL;
        snd_config_t *type = NULL, *args = NULL;
        snd_config_iterator_t i, next;
@@ -347,7 +347,9 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_
        }
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "type") == 0) {
@@ -365,9 +367,14 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_
                SNDERR("type is not defined");
                return -EINVAL;
        }
+       err = snd_config_get_id(type, &id);
+       if (err < 0) {
+               SNDERR("unable to get id");
+               return err;
+       }
        err = snd_config_get_string(type, &str);
        if (err < 0) {
-               SNDERR("Invalid type for %s", snd_config_get_id(type));
+               SNDERR("Invalid type for %s", id);
                return err;
        }
        err = snd_config_search_definition(root, "pcm_hook_type", str, &type);
@@ -378,7 +385,9 @@ static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_
                }
                snd_config_for_each(i, next, type) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
@@ -446,7 +455,9 @@ int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name,
        snd_config_t *hooks = NULL;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
@@ -620,6 +631,7 @@ int _snd_pcm_hook_ctl_elems_install(snd_pcm_t *pcm, snd_config_t *conf)
        char ctl_name[16];
        snd_ctl_t *ctl;
        snd_sctl_t *sctl;
+       snd_config_t *pcm_conf = NULL;
        snd_pcm_hook_t *h_hw_params = NULL, *h_hw_free = NULL, *h_close = NULL;
        assert(conf);
        assert(snd_config_get_type(conf) == SND_CONFIG_TYPE_COMPOUND);
@@ -638,9 +650,13 @@ int _snd_pcm_hook_ctl_elems_install(snd_pcm_t *pcm, snd_config_t *conf)
                SNDERR("Cannot open CTL %s", ctl_name);
                return err;
        }
-       err = snd_sctl_build(&sctl, ctl, conf, pcm, 0);
+       err = snd_config_make_pointer(&pcm_conf, "pcm_handle");
        if (err < 0)
-               return -ENOMEM;
+               goto _err;
+       snd_config_set_pointer(pcm_conf, pcm);
+       err = snd_sctl_build(&sctl, ctl, conf, pcm_conf, 0);
+       if (err < 0)
+               goto _err;
        err = snd_pcm_hook_add(&h_hw_params, pcm, SND_PCM_HOOK_TYPE_HW_PARAMS,
                               snd_pcm_hook_ctl_elems_hw_params, sctl);
        if (err < 0)
@@ -662,5 +678,7 @@ int _snd_pcm_hook_ctl_elems_install(snd_pcm_t *pcm, snd_config_t *conf)
        if (h_close)
                snd_pcm_hook_remove(h_close);
        snd_sctl_free(sctl);
+       if (pcm_conf)
+               snd_config_delete(pcm_conf);
        return err;
 }
index 9bdaf5abe2caa9a1cc4c6763ee9c3893b1ddf57a..023b6c1d0687fc7f5aa25b023c7f0b9db6b45f76 100644 (file)
@@ -669,7 +669,9 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
        int err;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "card") == 0) {
index ca33a48cd7ffdbe7cb033c4ee857f2a14ec33fcb..10147aabaa2f4c05d2b21be60376f0057b11a92e 100644 (file)
@@ -335,7 +335,9 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
        snd_pcm_format_t sformat;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index bde9bb63d8debfc36dd1de4e80de2aaa7c98e500..363b8451623ff8ad750939cd3a5d81aec98f8c52 100644 (file)
@@ -663,6 +663,7 @@ static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name,
 {
        char buf[256];
        snd_config_iterator_t i, next;
+       const char *id;
        const char *lib = NULL, *open_name = NULL, *str = NULL;
        snd_config_t *c, *type_conf;
        int (*open_func)(snd_pcm_t *, const char *,
@@ -679,16 +680,23 @@ static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name,
                SNDERR("type is not defined");
                goto _err;
        }
+       err = snd_config_get_id(c, &id);
+       if (err < 0) {
+               SNDERR("unable to get id");
+               goto _err;
+       }
        err = snd_config_get_string(c, &str);
        if (err < 0) {
-               SNDERR("Invalid type for %s", snd_config_get_id(c));
+               SNDERR("Invalid type for %s", id);
                goto _err;
        }
        err = snd_config_search_definition(root, "pcm_scope_type", str, &type_conf);
        if (err >= 0) {
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
@@ -745,7 +753,9 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
        snd_config_t *scopes = NULL;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
@@ -791,8 +801,9 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
                return 0;
        snd_config_for_each(i, next, scopes) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
-               const char *str;
+               const char *id, *str;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_config_get_string(n, &str) >= 0) {
                        err = snd_config_search_definition(root, "pcm_scope", str, &n);
                        if (err < 0) {
index 461a64a35c7d952cdd263f35560bbaf3db7fc3e2..d951c5cfc688eb4f164c434a22cc4c50f9b0bd82 100644 (file)
@@ -445,7 +445,9 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
        snd_pcm_format_t sformat;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index 5c6fe74b1584719efc4a2107274e2ead2691b675..0a9de427b0ea98bde7e51f7faff7861245e112fb 100644 (file)
@@ -684,7 +684,9 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
        unsigned int channels_count = 0;
        snd_config_for_each(i, inext, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slaves") == 0) {
@@ -731,7 +733,9 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
        snd_config_for_each(i, inext, bindings) {
                long cchannel;
                snd_config_t *m = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(m);
+               const char *id;
+               if (snd_config_get_id(m, &id) < 0)
+                       continue;
                err = safe_strtol(id, &cchannel);
                if (err < 0 || cchannel < 0) {
                        SNDERR("Invalid channel number: %s", id);
@@ -756,8 +760,11 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
        idx = 0;
        snd_config_for_each(i, inext, slaves) {
                snd_config_t *m = snd_config_iterator_entry(i);
+               const char *id;
                int channels;
-               slaves_id[idx] = snd_config_get_id(m);
+               if (snd_config_get_id(m, &id) < 0)
+                       continue;
+               slaves_id[idx] = id;
                err = snd_pcm_slave_conf(root, m, &slaves_conf[idx], 1,
                                         SND_PCM_HW_PARAM_CHANNELS, SCONF_MANDATORY, &channels);
                if (err < 0)
@@ -773,7 +780,9 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
                int slave = -1;
                long val;
                const char *str;
-               const char *id = snd_config_get_id(m);
+               const char *id;
+               if (snd_config_get_id(m, &id) < 0)
+                       continue;
                err = safe_strtol(id, &cchannel);
                if (err < 0 || cchannel < 0) {
                        SNDERR("Invalid channel number: %s", id);
@@ -782,7 +791,9 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
                }
                snd_config_for_each(j, jnext, m) {
                        snd_config_t *n = snd_config_iterator_entry(j);
-                       id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "slave") == 0) {
@@ -817,13 +828,13 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
                        goto _free;
                }
                if (slave < 0 || (unsigned int)slave >= slaves_count) {
-                       SNDERR("Invalid or missing sidx");
+                       SNDERR("Invalid or missing sidx for channel %s", id);
                        err = -EINVAL;
                        goto _free;
                }
                if (schannel < 0 || 
                    (unsigned int) schannel >= slaves_channels[slave]) {
-                       SNDERR("Invalid or missing schannel");
+                       SNDERR("Invalid or missing schannel for channel %s", id);
                        err = -EINVAL;
                        goto _free;
                }
index cac6f1895993bfbbc0e36c4c787519f77c209a68..4e30cab48c51cdfe710ecb59f00fc24b7750ff9d 100644 (file)
@@ -376,7 +376,9 @@ int _snd_pcm_null_open(snd_pcm_t **pcmp, const char *name,
        snd_config_iterator_t i, next;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                SNDERR("Unknown field %s", id);
index d00e91dbd8daf258de55d781b89b218f42b1e5d8..db002222a04f895ed8c7db23a94f35a412addc36 100644 (file)
@@ -828,7 +828,9 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
        int schannels = -1, srate = -1;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index ed65dccbafff65312389dcbe53a6504742082f6b..b7cd5012aee7d42d71f2d680ecaded29a5da83c2 100644 (file)
@@ -545,7 +545,9 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
        int srate = -1;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index debcc8caa15c577d34430472b0b3cfe7f6739326..769079d4a232fb95c507ae359a4fefcfec13fe4b 100644 (file)
@@ -796,10 +796,13 @@ int snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_entry_t *tt
                snd_config_t *in = snd_config_iterator_entry(i);
                snd_config_iterator_t j, jnext;
                long cchannel;
-               err = safe_strtol(snd_config_get_id(in), &cchannel);
+               const char *id;
+               if (!snd_config_get_id(in, &id) < 0)
+                       continue;
+               err = safe_strtol(id, &cchannel);
                if (err < 0 || 
                    cchannel < 0 || (unsigned int) cchannel > tt_csize) {
-                       SNDERR("Invalid client channel: %s", snd_config_get_id(in));
+                       SNDERR("Invalid client channel: %s", id);
                        return -EINVAL;
                }
                if (snd_config_get_type(in) != SND_CONFIG_TYPE_COMPOUND)
@@ -808,7 +811,9 @@ int snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_entry_t *tt
                        snd_config_t *jnode = snd_config_iterator_entry(j);
                        double value;
                        long schannel;
-                       const char *id = snd_config_get_id(jnode);
+                       const char *id;
+                       if (snd_config_get_id(jnode, &id) < 0)
+                               continue;
                        err = safe_strtol(id, &schannel);
                        if (err < 0 || 
                            schannel < 0 || (unsigned int) schannel > tt_ssize || 
@@ -855,7 +860,9 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
        unsigned int cused, sused;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
index 9b1d28bae3dd14a5cd7d05acaab07029b4d6a5c1..3ea7dde9f8a19c572e652351e91078ff0054cb65 100644 (file)
@@ -1388,7 +1388,9 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
        
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "slave") == 0) {
@@ -1436,7 +1438,9 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
        snd_config_for_each(i, next, bindings) {
                long cchannel = -1;
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                err = safe_strtol(id, &cchannel);
                if (err < 0 || cchannel < 0) {
                        SNDERR("Invalid client channel in binding: %s", id);
@@ -1455,9 +1459,11 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
 
        snd_config_for_each(i, next, bindings) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
                long cchannel;
                long schannel = -1;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                cchannel = atoi(id);
                err = snd_config_get_integer(n, &schannel);
                if (err < 0) {
index 1851a02aad3e29bf081721aff6cf6b98b8cf42e0..cb6b0cfba3bd134a8699a0ee1f73453b7e6f071f 100644 (file)
@@ -740,7 +740,9 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name,
        struct hostent *h;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (snd_pcm_conf_generic_id(id))
                        continue;
                if (strcmp(id, "server") == 0) {
@@ -781,7 +783,9 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name,
        }
        snd_config_for_each(i, next, sconfig) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "host") == 0) {
index 4cf1efa80f82d586991303d50e68bf4d5bb00287..1d136d20288c1ac685d92994586bd15a5f062fc5 100644 (file)
@@ -71,6 +71,7 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp
        snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
        snd_rawmidi_params_t params;
+       const char *id;
        const char *lib = NULL, *open_name = NULL;
        int (*open_func)(snd_rawmidi_t **, snd_rawmidi_t **,
                         const char *, snd_config_t *, snd_config_t *, int) = NULL;
@@ -90,9 +91,14 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp
                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", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return err;
        }
        err = snd_config_search_definition(rawmidi_root, "rawmidi_type", str, &type_conf);
@@ -103,7 +109,9 @@ static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp
                }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
index 07011d43acece93f991634088890a1d4868997dc..97eb51f5ad83473a4a4e2714cabf9d38dbcddf0f 100644 (file)
@@ -317,7 +317,9 @@ int _snd_rawmidi_hw_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
        int err;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "type") == 0)
index da51aa106f09e9a8d631f931d7a2d6b7086731ab..da04532ef779eecd91bb93a70bde3f7c12f476a7 100644 (file)
@@ -73,6 +73,7 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name,
        int err;
        snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
+       const char *id;
        const char *lib = NULL, *open_name = NULL;
        int (*open_func)(snd_seq_t **, const char *,
                         snd_config_t *, snd_config_t *, 
@@ -93,9 +94,14 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name,
                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", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return err;
        }
        err = snd_config_search_definition(seq_root, "seq_type", str, &type_conf);
@@ -106,7 +112,9 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name,
                }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
index 38a30e6982aecfa1d5f80a0eb6f4c6a66670a8c7..f7d128ec3662ae713f3f1afe6d94869c187cfc99 100644 (file)
@@ -515,7 +515,9 @@ int _snd_seq_hw_open(snd_seq_t **handlep, char *name,
        snd_config_iterator_t i, next;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "type") == 0)
index 297b3cf0f64c0e0534e46c5240394503d134559e..248068995eb14f0c26fdb1dbe89c87394b8eb7ff 100644 (file)
@@ -45,6 +45,7 @@ static int snd_timer_open_conf(snd_timer_t **timer,
        int err;
        snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
+       const char *id;
        const char *lib = NULL, *open_name = NULL;
        int (*open_func)(snd_timer_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL;
 #ifndef PIC
@@ -63,9 +64,14 @@ static int snd_timer_open_conf(snd_timer_t **timer,
                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", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return err;
        }
        err = snd_config_search_definition(timer_root, "timer_type", str, &type_conf);
@@ -76,7 +82,9 @@ static int snd_timer_open_conf(snd_timer_t **timer,
                }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
index 7921c9e7d8d73d72f06bb251952979a19c4c3ba6..9400e989b25314a505bb7f73e5f2136512135077 100644 (file)
@@ -216,7 +216,9 @@ int _snd_timer_hw_open(snd_timer_t **timer, char *name,
        int err;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "type") == 0)
index fe24fa66afe9d31535c30c92fd21c63d214bab33..84559a7fa345dc75835fe3fe2391253f83185719 100644 (file)
@@ -44,6 +44,7 @@ static int snd_timer_query_open_conf(snd_timer_query_t **timer,
        int err;
        snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
+       const char *id;
        const char *lib = NULL, *open_name = NULL;
        int (*open_func)(snd_timer_query_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL;
 #ifndef PIC
@@ -62,9 +63,14 @@ static int snd_timer_query_open_conf(snd_timer_query_t **timer,
                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", snd_config_get_id(conf));
+               SNDERR("Invalid type for %s", id);
                return err;
        }
        err = snd_config_search_definition(timer_root, "timer_query_type", str, &type_conf);
@@ -75,7 +81,9 @@ static int snd_timer_query_open_conf(snd_timer_query_t **timer,
                }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
-                       const char *id = snd_config_get_id(n);
+                       const char *id;
+                       if (snd_config_get_id(n, &id) < 0)
+                               continue;
                        if (strcmp(id, "comment") == 0)
                                continue;
                        if (strcmp(id, "lib") == 0) {
index a7b84505d6a216fa3fab3e414d18f94bf04da38a..5b80c678b83fe5bba98d875806d8b58107ef30e7 100644 (file)
@@ -100,7 +100,9 @@ int _snd_timer_query_hw_open(snd_timer_query_t **timer, char *name,
        snd_config_iterator_t i, next;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               const char *id = snd_config_get_id(n);
+               const char *id;
+               if (snd_config_get_id(n, &id) < 0)
+                       continue;
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "type") == 0)