Configuring the PCM device

The next step in playing back or capturing the sound stream is to inform the device of the format of the data that you're about to send it or want to receive from it.

You can do this by filling in a snd_pcm_channel_params_t structure, and then calling snd_pcm_channel_params() or snd_pcm_plugin_params(). The difference between the functions is that the second one uses the plugin converters (see "PCM plugin converters" in the Audio Architecture chapter) if required.

If the device can't support the data parameters you're setting, or if all the subchannels of the device are currently in use, both of these functions fail.

The API calls for determining the current capabilities of a PCM device are:

Use the plugin converters. If the hardware has a free subchannel, the capabilities returned are extensive because the plugin converters make any necessary conversion.
Access the hardware directly. This function returns only what the hardware capabilities are.
Note: Both of these functions take as an argument a pointer to a snd_pcm_channel_info_t structure. You must set the channel member of this structure to the desired direction (SND_PCM_CHANNEL_CAPTURE or SND_PCM_CHANNEL_PLAYBACK) before calling the functions. The functions fill in the other members of the structure.

It's the act of configuring the channel that allocates a subchannel to the client. Stated another way, hundreds of clients can open a handle to a PCM device with only one subchannel, but only one can configure it. After a client allocates a subchannel, it isn't returned to the free pool until the handle is closed. One result of this mechanism is that, from moment to moment, the capabilities of a PCM device change as other applications allocate and free subchannels. Additionally the act of configuring / allocating a subchannel changes its state from SND_PCM_STATUS_NOTREADY to SND_PCM_STATUS_READY.

If the API call succeeds, all parameters specified are accepted and are guaranteed to be in effect, except for the frag_size parameter, which is only a suggestion to the hardware. The hardware may adjust the fragment size, based on hardware requirements. For example, if the hardware can't deal with fragments crossing 64-kilobyte boundaries, and the suggested frag_size is 60 kilobytes, the driver will probably adjust it to 64 kilobytes.

Another aspect of configuration is determining how big to make the hardware buffer. This determines how much latency that the application has when sending data to the driver or reading data from it. The hardware buffer size is determined by multiplying the frag_size by the max_frags parameter, so for the application to know the buffer size, it must determine the actual frag_size that the driver is using.

You can do this by calling snd_pcm_channel_setup() or snd_pcm_plugin_setup(), depending on whether or not your application is using the plugin converters. Both of these functions take as an argument a pointer to a snd_pcm_channel_setup_t structure that they fill with information about how the channel is configured, including the true frag_size.