xref: /third_party/alsa-lib/src/pcm/pcm.c (revision d5ac70f0)
1/**
2 * \file pcm/pcm.c
3 * \ingroup PCM
4 * \brief PCM Interface
5 * \author Jaroslav Kysela <perex@perex.cz>
6 * \author Abramo Bagnara <abramo@alsa-project.org>
7 * \date 2000-2001
8 *
9 * PCM Interface is designed to write or read digital audio frames. A
10 * frame is the data unit converted into/from sound in one time unit
11 * (1/rate seconds), by example if you set your playback PCM rate to
12 * 44100 you'll hear 44100 frames per second. The size in bytes of a
13 * frame may be obtained from bits needed to store a sample and
14 * channels count.
15 *
16 * See the \ref pcm page for more details.
17 */
18/*
19 *  PCM Interface - main file
20 *  Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz>
21 *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
22 *
23 *   This library is free software; you can redistribute it and/or modify
24 *   it under the terms of the GNU Lesser General Public License as
25 *   published by the Free Software Foundation; either version 2.1 of
26 *   the License, or (at your option) any later version.
27 *
28 *   This program is distributed in the hope that it will be useful,
29 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
30 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31 *   GNU Lesser General Public License for more details.
32 *
33 *   You should have received a copy of the GNU Lesser General Public
34 *   License along with this library; if not, write to the Free Software
35 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
36 *
37 */
38
39/*! \page pcm PCM (digital audio) interface
40
41<P>Although abbreviation PCM stands for Pulse Code Modulation, we are
42understanding it as general digital audio processing with volume samples
43generated in continuous time periods.</P>
44
45<P>The analog signal is recorded via analog to digital converters (ADC).
46The digital value (de-facto a volume at a specific time) obtained
47from ADC can be further processed. The following picture shows a perfect
48sinus waveform:</P>
49
50<BR>
51\image html wave1.gif
52
53<P>Next image shows digitized representation:</P>
54
55<BR>
56\image html wave2.gif
57
58<P>As you may see, the quality of digital audio signal depends on the time
59(recording rate) and voltage resolution (usually in an linear integer
60representation with basic unit one bit).</P>
61
62<P>The stored digital signal can be converted back to voltage (analog)
63representation via digital to analog converters (DAC).</P>
64
65<P>One digital value is called sample. More samples are collected to frames
66(frame is terminology for ALSA) depending on count of converters used at one
67specific time. One frame might contain one sample (when only one converter is
68used - mono) or more samples (for example: stereo has signals from two converters
69recorded at same time). Digital audio stream contains collection of frames
70recorded at boundaries of continuous time periods.</P>
71
72\section pcm_general_overview General overview
73
74ALSA uses the ring buffer to store outgoing (playback) and incoming (capture,
75record) samples. There are two pointers being maintained to allow
76a precise communication between application and device pointing to current
77processed sample by hardware and last processed sample by application.
78The modern audio chips allow to program the transfer time periods.
79It means that the stream of samples is divided to small chunks. Device
80acknowledges to application when the transfer of a chunk is complete.
81
82\section pcm_transfer Transfer methods in UNIX environments
83
84In the UNIX environment, data chunk acknowledges are received via standard I/O
85calls or event waiting routines (poll or select function). To accomplish
86this list, the asynchronous notification of acknowledges should be listed
87here. The ALSA implementation for these methods is described in
88the \ref alsa_transfers section.
89
90\subsection pcm_transfer_io Standard I/O transfers
91
92The standard I/O transfers are using the read (see 'man 2 read') and write
93(see 'man 2 write') C functions. There are two basic behaviours of these
94functions - blocked and non-blocked (see the O_NONBLOCK flag for the
95standard C open function - see 'man 2 open'). In non-blocked behaviour,
96these I/O functions never stops, they return -EAGAIN error code, when no
97data can be transferred (the ring buffer is full in our case). In blocked
98behaviour, these I/O functions stop and wait until there is a room in the
99ring buffer (playback) or until there are new samples (capture). The ALSA
100implementation can be found in the \ref alsa_pcm_rw section.
101
102\subsection pcm_transfer_event Event waiting routines
103
104The poll or select functions (see 'man 2 poll' or 'man 2 select' for further
105details) allows to receive requests/events from the device while
106an application is waiting on events from other sources (like keyboard, screen,
107network etc.), too. \ref snd_pcm_poll_descriptors can be used to get file
108descriptors to poll or select on (note that wait direction might be different
109than expected - do not use only returned file descriptors, but handle
110events member as well - see \ref snd_pcm_poll_descriptors function
111description for more details and \ref snd_pcm_poll_descriptors_revents for
112events demangling). The implemented transfer routines can be found in
113the \ref alsa_transfers section.
114
115\subsection pcm_transfer_async Asynchronous notification
116
117ALSA driver and library knows to handle the asynchronous notifications over
118the SIGIO signal. This signal allows to interrupt application and transfer
119data in the signal handler. For further details see the sigaction function
120('man 2 sigaction'). The section \ref pcm_async describes the ALSA API for
121this extension. The implemented transfer routines can be found in the
122\ref alsa_transfers section.
123
124\section pcm_open_behaviour Blocked and non-blocked open
125
126The ALSA PCM API uses a different behaviour when the device is opened
127with blocked or non-blocked mode. The mode can be specified with
128\a mode argument in #snd_pcm_open() function.
129The blocked mode is the default (without #SND_PCM_NONBLOCK mode).
130In this mode, the behaviour is that if the resources have already used
131with another application, then it blocks the caller, until resources are
132free. The non-blocked behaviour (with #SND_PCM_NONBLOCK)
133doesn't block the caller in any way and returns -EBUSY error when the
134resources are not available. Note that the mode also determines the
135behaviour of standard I/O calls, returning -EAGAIN when non-blocked mode is
136used and the ring buffer is full (playback) or empty (capture).
137The operation mode for I/O calls can be changed later with
138the #snd_pcm_nonblock() function.
139
140\section pcm_async Asynchronous mode
141
142There is also possibility to receive asynchronous notification after
143specified time periods. You may see the #SND_PCM_ASYNC
144mode for #snd_pcm_open() function and
145#snd_async_add_pcm_handler() function for further details.
146
147\section pcm_handshake Handshake between application and library
148
149The ALSA PCM API design uses the states to determine the communication
150phase between application and library. The actual state can be determined
151using #snd_pcm_state() call. There are these states:
152
153\par SND_PCM_STATE_OPEN
154The PCM device is in the open state. After the #snd_pcm_open() open call,
155the device is in this state. Also, when #snd_pcm_hw_params() call fails,
156then this state is entered to force application calling
157#snd_pcm_hw_params() function to set right communication
158parameters.
159
160\par SND_PCM_STATE_SETUP
161The PCM device has accepted communication parameters and it is waiting
162for #snd_pcm_prepare() call to prepare the hardware for
163selected operation (playback or capture).
164
165\par SND_PCM_STATE_PREPARED
166The PCM device is prepared for operation. Application can use
167#snd_pcm_start() call, write or read data to start
168the operation.
169
170\par SND_PCM_STATE_RUNNING
171The PCM device has been started and is running. It processes the samples. The stream can
172be stopped using the #snd_pcm_drop() or
173#snd_pcm_drain() calls.
174
175\par SND_PCM_STATE_XRUN
176The PCM device reached overrun (capture) or underrun (playback).
177You can use the -EPIPE return code from I/O functions
178(#snd_pcm_writei(), #snd_pcm_writen(), #snd_pcm_readi(), #snd_pcm_readn())
179to determine this state without checking
180the actual state via #snd_pcm_state() call. It is recommended to use
181the helper function #snd_pcm_recover() to recover from this state, but you can also use #snd_pcm_prepare(),
182#snd_pcm_drop() or #snd_pcm_drain() calls.
183
184\par SND_PCM_STATE_DRAINING
185The device is in this state when application using the capture mode
186called #snd_pcm_drain() function. Until all data are
187read from the internal ring buffer using I/O routines
188(#snd_pcm_readi(), #snd_pcm_readn()),
189then the device stays in this state.
190
191\par SND_PCM_STATE_PAUSED
192The device is in this state when application called
193the #snd_pcm_pause() function until the pause is released.
194Not all hardware supports this feature. Application should check the
195capability with the #snd_pcm_hw_params_can_pause().
196
197\par SND_PCM_STATE_SUSPENDED
198The device is in the suspend state provoked with the power management
199system. The stream can be resumed using #snd_pcm_resume()
200call, but not all hardware supports this feature. Application should check
201the capability with the #snd_pcm_hw_params_can_resume().
202In other case, the calls #snd_pcm_prepare(),
203#snd_pcm_drop(), #snd_pcm_drain() can be used
204to leave this state.
205
206\par SND_PCM_STATE_DISCONNECTED
207The device is physicaly disconnected. It does not accept any I/O calls in this state.
208
209\section pcm_formats PCM formats
210
211The full list of formats present the #snd_pcm_format_t type.
212The 24-bit linear samples use 32-bit physical space, but the sample is
213stored in the lower three bytes. Some hardware does not support processing of full
214range, thus you may get the significant bits for linear samples via
215#snd_pcm_hw_params_get_sbits() function. The example: ICE1712
216chips support 32-bit sample processing, but low byte is ignored (playback)
217or zero (capture). The function snd_pcm_hw_params_get_sbits()
218returns 24 in this case. The significant bits are related to the usable
219sample bits (width) not the physical sample space.
220
221\section alsa_transfers ALSA transfers
222
223There are two methods to transfer samples in application. The first method
224is the standard read / write one. The second method, uses the direct audio
225buffer to communicate with the device while ALSA library manages this space
226itself. You can find examples of all communication schemes for playback
227in \link example_test_pcm Sine-wave generator example \endlink. To complete the
228list, we should note that #snd_pcm_wait() function contains
229embedded poll waiting implementation.
230
231\subsection alsa_pcm_rw Read / Write transfer
232
233There are two versions of read / write routines. The first expects the
234interleaved samples at input (#SND_PCM_ACCESS_RW_INTERLEAVED access method),
235and the second one expects non-interleaved (samples in separated buffers -
236#SND_PCM_ACCESS_RW_NONINTERLEAVED access method) at input. There are these
237functions for interleaved transfers: #snd_pcm_writei()
238#snd_pcm_readi(). For non-interleaved transfers, there are
239these functions: #snd_pcm_writen() and #snd_pcm_readn().
240
241\subsection alsa_mmap_rw Direct Read / Write transfer (via mmap'ed areas)
242
243Three kinds of organization of ring buffer memory areas exist in ALSA API.
244Access #SND_PCM_ACCESS_MMAP_INTERLEAVED has interleaved samples. Access
245#SND_PCM_ACCESS_MMAP_NONINTERLEAVED expects continous sample areas for
246one channel. Access #SND_PCM_ACCESS_MMAP_COMPLEX does not fit to interleaved
247and non-interleaved ring buffer organization.
248
249There are two functions for this kind of transfer. Application can get an
250access to memory areas via #snd_pcm_mmap_begin() function.
251This function returns the areas (single area is equal to a channel)
252containing the direct pointers to memory and sample position description
253in #snd_pcm_channel_area_t structure. After application
254transfers the data in the memory areas, then it must be acknowledged
255the end of transfer via #snd_pcm_mmap_commit() function
256to allow the ALSA library update the pointers to ring buffer. This kind of
257communication is also called "zero-copy", because the device does not require
258to copy the samples from application to another place in system memory.
259
260If you like to use the compatibility functions in mmap mode, there are
261read / write routines equaling to standard read / write transfers. Using
262these functions discards the benefits of direct access to memory region.
263See the #snd_pcm_mmap_readi(),
264#snd_pcm_mmap_writei(), #snd_pcm_mmap_readn()
265and #snd_pcm_mmap_writen() functions. These functions use
266#snd_pcm_areas_copy() internally.
267
268\section pcm_errors Error codes
269
270\par -EPIPE
271
272This error means xrun (underrun for playback or overrun for capture).
273The underrun can happen when an application does not feed new samples
274in time to alsa-lib (due CPU usage). The overrun can happen when
275an application does not take new captured samples in time from alsa-lib.
276
277\par -ESTRPIPE
278
279This error means that system has suspended drivers. The application
280should wait in loop when snd_pcm_resume() != -EAGAIN and then
281call snd_pcm_prepare() when snd_pcm_resume() return an error code.
282If snd_pcm_resume() does not fail (a zero value is returned), driver
283supports resume and the snd_pcm_prepare() call can be ommited.
284
285\par -EBADFD
286
287This error means that the device is in a bad state. It means that
288the handshake between application and alsa-lib is corrupted.
289
290\par -ENOTTY, -ENODEV
291
292This error can happen when device is physically removed (for example
293some hotplug devices like USB or PCMCIA, CardBus or ExpressCard
294can be removed on the fly).
295
296\par -ENODATA
297
298This error can happen if the device data transfer is dependent on
299an external condition and that condition is not met. For example,
300PCM device for echo reference as described by SND_USE_CASE_MOD_ECHO_REF
301UCM token, may return -ENODATA if the linked playback stream has not been
302started.
303
304There is no defined recovery or event mechanism to signal the data / link
305availability at the moment. The PCM must be completely restarted until
306the mechanism is designed. The #snd_pcm_recover() function cannot be
307used for this.
308
309\section pcm_params Managing parameters
310
311The ALSA PCM device uses two groups of PCM related parameters. The hardware
312parameters contains the stream description like format, rate, count of
313channels, ring buffer size etc. The software parameters contains the
314software (driver) related parameters. The communication behaviour can be
315controlled via these parameters, like automatic start, automatic stop,
316interrupting (chunk acknowledge) etc. The software parameters can be
317modified at any time (when valid hardware parameters are set). It includes
318the running state as well.
319
320\subsection pcm_hw_params Hardware related parameters
321
322The ALSA PCM devices use the parameter refining system for hardware
323parameters - #snd_pcm_hw_params_t. It means, that
324application choose the full-range of configurations at first and then
325application sets single parameters until all parameters are elementary
326(definite).
327
328\par Access modes
329
330ALSA knows about five access modes. The first three can be used for direct
331communication. The access mode #SND_PCM_ACCESS_MMAP_INTERLEAVED
332determines the direct memory area and interleaved sample organization.
333Interleaved organization means, that samples from channels are mixed together.
334The access mode #SND_PCM_ACCESS_MMAP_NONINTERLEAVED
335determines the direct memory area and non-interleaved sample organization.
336Each channel has a separate buffer in the case. The complex direct memory
337organization represents the #SND_PCM_ACCESS_MMAP_COMPLEX
338access mode. The sample organization does not fit the interleaved or
339non-interleaved access modes in the case. The last two access modes
340describes the read / write access methods.
341The #SND_PCM_ACCESS_RW_INTERLEAVED access represents the read /
342write interleaved access and the #SND_PCM_ACCESS_RW_NONINTERLEAVED
343represents the non-interleaved access.
344
345\par Formats
346
347The full list of formats is available in #snd_pcm_format_t
348enumeration.
349
350\subsection pcm_sw_params Software related parameters
351
352These parameters - #snd_pcm_sw_params_t can be modified at
353any time including the running state.
354
355\par Minimum available count of frames
356
357This parameter controls the wakeup point. If the count of available frames
358is equal or greater than this value, then application will be activated.
359
360\par Timestamp mode
361
362The timestamp mode specifies, if timestamps are activated. Currently, only
363#SND_PCM_TSTAMP_NONE and #SND_PCM_TSTAMP_MMAP
364modes are known. The mmap mode means that timestamp is taken
365on every period time boundary. Corresponding position in the ring buffer
366assigned to timestamp can be obtained using #snd_pcm_htimestamp() function.
367
368\par Transfer align
369
370The read / write transfers can be aligned to this sample count. The modulo
371is ignored by device. Usually, this value is set to one (no align).
372
373\par Start threshold
374
375The start threshold parameter is used to determine the start point in
376stream. For playback, if the frame count in the ring buffer is equal or greater
377than the start threshold parameter and the stream is not running, the stream
378will be started automatically from the device. For capture, if the application
379wants to read count of frames equal or greater then the stream will be started.
380If you want to use explicit start (#snd_pcm_start), you can set this value
381greater than the ring buffer size (in frames). For that simply using a large
382constant such as LONG_MAX or the boundary value is not a bad idea.
383
384\par Stop threshold
385
386Similarly, the stop threshold parameter is used to automatically stop
387the running stream, when the available frames crosses this boundary.
388It means, for playback, the empty samples in ring buffer and for capture,
389the filled (used) samples in ring buffer.
390
391\par Silence threshold
392
393The silence threshold specifies the count of frames before an underrun when the
394buffer gets filled with frames of silence according to the silence size parameter
395ahead of the current application pointer for playback. It is usable for applications
396when an underrun is possible (like tasks depending on network I/O etc.). If
397application wants to manage the ahead samples itself, the #snd_pcm_rewind() function
398allows to forget the last samples in the stream.
399
400\section pcm_status Obtaining stream status
401
402The stream status is stored in #snd_pcm_status_t structure.
403These parameters can be obtained: the current stream state -
404#snd_pcm_status_get_state(), timestamp of trigger -
405#snd_pcm_status_get_trigger_tstamp(), timestamp of last
406pointer update #snd_pcm_status_get_tstamp(), delay in frames -
407#snd_pcm_status_get_delay(), available count in frames -
408#snd_pcm_status_get_avail(), maximum available frames -
409#snd_pcm_status_get_avail_max(), ADC over-range count in
410frames - #snd_pcm_status_get_overrange(). The last two
411parameters - avail_max and overrange are reset to zero after the status
412call.
413
414\subsection pcm_status_fast Obtaining stream state fast and update r/w pointer
415
416<p>
417The function #snd_pcm_avail_update() updates the current
418available count of frames for writing (playback) or filled frames for
419reading (capture). This call is mandatory for updating actual r/w pointer.
420Using standalone, it is a light method to obtain current stream position,
421because it does not require the user <-> kernel context switch, but the value
422is less accurate, because ring buffer pointers are updated in kernel drivers
423only when an interrupt occurs. If you want to get accurate stream state,
424use functions #snd_pcm_avail(), #snd_pcm_delay() or #snd_pcm_avail_delay().
425</p>
426<p>
427The function #snd_pcm_avail() reads the current hardware pointer
428in the ring buffer from hardware and calls #snd_pcm_avail_update() then.
429</p>
430<p>
431The function #snd_pcm_delay() returns the delay in frames.
432For playback, it means count of frames in the ring buffer before
433the next frames will be sent to DAC. For capture, it means count of frames
434in the ring buffer before the next frames will be captured from ADC. It works
435only when the stream is in the running or draining (playback only) state.
436Note that this function does not update the current r/w pointer for applications,
437so the function #snd_pcm_avail_update() must be called afterwards
438before any read/write begin+commit operations.
439</p>
440<p>
441The function #snd_pcm_avail_delay() combines #snd_pcm_avail() and
442#snd_pcm_delay() and returns both values in sync.
443</p>
444
445\section pcm_action Managing the stream state
446
447The following functions directly and indirectly affect the stream state:
448
449\par snd_pcm_hw_params
450The #snd_pcm_hw_params() function brings the stream state
451to #SND_PCM_STATE_SETUP
452if successfully finishes, otherwise the state #SND_PCM_STATE_OPEN
453is entered.
454When it is brought to SETUP state, this function automatically
455calls #snd_pcm_prepare() function to bring to the PREPARED state
456as below.
457
458\par snd_pcm_prepare
459The #snd_pcm_prepare() function enters from #SND_PCM_STATE_SETUP
460to the #SND_PCM_STATE_PREPARED after a successful finish.
461
462\par snd_pcm_start
463The #snd_pcm_start() function enters
464the #SND_PCM_STATE_RUNNING after a successful finish.
465
466\par snd_pcm_drop
467The #snd_pcm_drop() function enters the
468#SND_PCM_STATE_SETUP state.
469
470\par snd_pcm_drain
471The #snd_pcm_drain() function enters the
472#SND_PCM_STATE_DRAINING, if
473the capture device has some samples in the ring buffer otherwise
474#SND_PCM_STATE_SETUP state is entered.
475
476\par snd_pcm_pause
477The #snd_pcm_pause() function enters the
478#SND_PCM_STATE_PAUSED or #SND_PCM_STATE_RUNNING.
479
480\par snd_pcm_writei, snd_pcm_writen
481The #snd_pcm_writei() and #snd_pcm_writen()
482functions can conditionally start the stream -
483#SND_PCM_STATE_RUNNING. They depend on the start threshold
484software parameter.
485
486\par snd_pcm_readi, snd_pcm_readn
487The #snd_pcm_readi() and #snd_pcm_readn()
488functions can conditionally start the stream -
489#SND_PCM_STATE_RUNNING. They depend on the start threshold
490software parameter.
491
492\section pcm_sync Streams synchronization
493
494There are two functions allowing link multiple streams together. In the
495case, the linking means that all operations are synchronized. Because the
496drivers cannot guarantee the synchronization (sample resolution) on hardware
497lacking this feature, the #snd_pcm_info_get_sync() function
498returns synchronization ID - #snd_pcm_sync_id_t, which is equal
499for hardware synchronized streams. When the #snd_pcm_link()
500function is called, all operations managing the stream state for these two
501streams are joined. The opposite function is #snd_pcm_unlink().
502
503\section pcm_thread_safety Thread-safety
504
505When the library is configured with the proper option, some PCM functions
506(e.g. #snd_pcm_avail_update()) are thread-safe and can be called concurrently
507from multiple threads.  Meanwhile, some functions (e.g. #snd_pcm_hw_params())
508aren't thread-safe, and application needs to call them carefully when they
509are called from multiple threads.  In general, all the functions that are
510often called during streaming are covered as thread-safe.
511
512This thread-safe behavior can be disabled also by passing 0 to the environment
513variable LIBASOUND_THREAD_SAFE, e.g.
514\code
515LIBASOUND_THREAD_SAFE=0 aplay foo.wav
516\endcode
517for making the debugging easier.
518
519\section pcm_dev_names PCM naming conventions
520
521The ALSA library uses a generic string representation for names of devices.
522The devices might be virtual, physical or a mix of both. The generic string
523is passed to #snd_pcm_open() or #snd_pcm_open_lconf().
524It contains two parts: device name and arguments. Devices and arguments are described
525in configuration files. The usual place for default definitions is at /usr/share/alsa/alsa.conf.
526For detailed descriptions about integrated PCM plugins look to \ref pcm_plugins.
527
528\subsection pcm_dev_names_default Default device
529
530The default device is equal to plug plugin with hw plugin as slave. The defaults are
531used:
532
533\code
534defaults.pcm.card 0
535defaults.pcm.device 0
536defaults.pcm.subdevice -1
537\endcode
538
539These defaults can be freely overwritten in local configuration files.
540
541Example:
542
543\code
544default
545\endcode
546
547\subsection pcm_dev_names_hw HW device
548
549The hw device description uses the hw plugin. The three arguments (in order: CARD,DEV,SUBDEV)
550specify card number or identifier, device number and subdevice number (-1 means any).
551
552Example:
553
554\code
555hw
556hw:0
557hw:0,0
558hw:supersonic,1
559hw:soundwave,1,2
560hw:DEV=1,CARD=soundwave,SUBDEV=2
561\endcode
562
563\subsection pcm_dev_names_plughw Plug->HW device
564
565The plughw device description uses the plug plugin and hw plugin as slave. The arguments
566are same as for hw device.
567
568Example:
569
570\code
571plughw
572plughw:0
573plughw:0,0
574plughw:supersonic,1
575plughw:soundwave,1,2
576plughw:DEV=1,CARD=soundwave,SUBDEV=2
577\endcode
578
579\subsection pcm_dev_names_plug Plug device
580
581The plug device uses the plug plugin. The one SLAVE argument specifies the slave plugin.
582
583Example:
584
585\code
586plug:mypcmdef
587plug:hw
588plug:'hw:0,0'
589plug:SLAVE=hw
590\endcode
591
592\subsection pcm_dev_names_shm Shared memory device
593
594The shm device uses the shm plugin. The two arguments (in order: SOCKET,PCM) specify
595UNIX socket name (for example /tmp/alsa.socket) for server communication and server's PCM name.
596
597Example:
598
599\code
600shm:'/tmp/alsa.sock',default
601shm:SOCKET='/tmp/alsa.sock',PCM=default
602\endcode
603
604\subsection pcm_dev_names_tee Tee device
605
606The tee device stores contents of a stream to given file plus transfers it to given slave plugin.
607The three arguments (in order: SLAVE,FILE,FORMAT) specify slave plugin, filename and file format.
608
609Example:
610
611\code
612tee:hw,'/tmp/out.raw',raw
613\endcode
614
615\subsection pcm_dev_names_file File device
616
617The file device is file plugin with null plugin as slave. The arguments (in order: FILE,FORMAT)
618specify filename and file format.
619
620Example:
621
622\code
623file:'/tmp/out.raw',raw
624\endcode
625
626\subsection pcm_dev_names_null Null device
627
628The null device is null plugin. This device has not any arguments.
629
630
631\section pcm_examples Examples
632
633The full featured examples with cross-links can be found in Examples section
634(see top of page):
635
636\par Sine-wave generator
637\par
638\link example_test_pcm alsa-lib/test/pcm.c \endlink
639example shows various transfer methods for the playback direction.
640
641\par Minimalistic PCM playback code
642\par
643\link example_test_minimal alsa-lib/test/pcm_min.c \endlink
644example shows the minimal code to produce a sound.
645
646\par Latency measuring tool
647\par
648\link example_test_latency alsa-lib/test/latency.c \endlink
649example shows the measuring of minimal latency between capture and
650playback devices.
651
652*/
653
654/**
655\example ../../test/pcm.c
656\anchor example_test_pcm
657Shows various transfer methods for the playback direction.
658*/
659/**
660\example ../../test/pcm_min.c
661\anchor example_test_minimal
662Shows the minimal code to produce a sound.
663*/
664/**
665\example ../../test/latency.c
666\anchor example_test_latency
667Shows the measuring of minimal latency between capture and
668playback devices.
669*/
670
671#include "pcm_local.h"
672#include <stdio.h>
673#include <string.h>
674#if HAVE_MALLOC_H
675#include <malloc.h>
676#endif
677#include <stdarg.h>
678#include <signal.h>
679#include <ctype.h>
680#include <poll.h>
681#include <sys/mman.h>
682#include <limits.h>
683
684#ifndef DOC_HIDDEN
685/* return specific error codes for known bad PCM states */
686static int pcm_state_to_error(snd_pcm_state_t state)
687{
688	switch (state) {
689	case SND_PCM_STATE_XRUN:
690		return -EPIPE;
691	case SND_PCM_STATE_SUSPENDED:
692		return -ESTRPIPE;
693	case SND_PCM_STATE_DISCONNECTED:
694		return -ENODEV;
695	default:
696		return 0;
697	}
698}
699
700#define P_STATE(x)	(1U << SND_PCM_STATE_ ## x)
701#define P_STATE_RUNNABLE (P_STATE(PREPARED) | \
702			  P_STATE(RUNNING) | \
703			  P_STATE(XRUN) | \
704			  P_STATE(PAUSED) | \
705			  P_STATE(DRAINING))
706
707/* check whether the PCM is in the unexpected state */
708static int bad_pcm_state(snd_pcm_t *pcm, unsigned int supported_states,
709			 unsigned int noop_states)
710{
711	snd_pcm_state_t state;
712	int err;
713
714	if (pcm->own_state_check)
715		return 0; /* don't care, the plugin checks by itself */
716	state = snd_pcm_state(pcm);
717	if (noop_states & (1U << state))
718		return 1; /* OK, return immediately */
719	if (supported_states & (1U << state))
720		return 0; /* OK */
721	err = pcm_state_to_error(state);
722	if (err < 0)
723		return err;
724	return -EBADFD;
725}
726#endif
727
728/**
729 * \brief get identifier of PCM handle
730 * \param pcm PCM handle
731 * \return ascii identifier of PCM handle
732 *
733 * Returns the ASCII identifier of given PCM handle. It's the same
734 * identifier specified in snd_pcm_open().
735 */
736const char *snd_pcm_name(snd_pcm_t *pcm)
737{
738	assert(pcm);
739	return pcm->name;
740}
741
742/**
743 * \brief get type of PCM handle
744 * \param pcm PCM handle
745 * \return type of PCM handle
746 *
747 * Returns the type #snd_pcm_type_t of given PCM handle.
748 */
749snd_pcm_type_t snd_pcm_type(snd_pcm_t *pcm)
750{
751	assert(pcm);
752	return pcm->type;
753}
754
755/**
756 * \brief get stream for a PCM handle
757 * \param pcm PCM handle
758 * \return stream of PCM handle
759 *
760 * Returns the type #snd_pcm_stream_t of given PCM handle.
761 */
762snd_pcm_stream_t snd_pcm_stream(snd_pcm_t *pcm)
763{
764	assert(pcm);
765	return pcm->stream;
766}
767
768/**
769 * \brief close PCM handle
770 * \param pcm PCM handle
771 * \return 0 on success otherwise a negative error code
772 *
773 * Closes the specified PCM handle and frees all associated
774 * resources.
775 */
776int snd_pcm_close(snd_pcm_t *pcm)
777{
778	int res = 0, err;
779	assert(pcm);
780	if (pcm->setup && !pcm->donot_close) {
781		snd_pcm_drop(pcm);
782		err = snd_pcm_hw_free(pcm);
783		if (err < 0)
784			res = err;
785	}
786	if (pcm->mmap_channels)
787		snd_pcm_munmap(pcm);
788	while (!list_empty(&pcm->async_handlers)) {
789		snd_async_handler_t *h = list_entry(pcm->async_handlers.next, snd_async_handler_t, hlist);
790		snd_async_del_handler(h);
791	}
792	if (pcm->ops->close)
793		err = pcm->ops->close(pcm->op_arg);
794	else
795		err = -ENOSYS;
796	if (err < 0)
797		res = err;
798	err = snd_pcm_free(pcm);
799	if (err < 0)
800		res = err;
801	return res;
802}
803
804/**
805 * \brief set nonblock mode
806 * \param pcm PCM handle
807 * \param nonblock 0 = block, 1 = nonblock mode, 2 = abort
808 * \return 0 on success otherwise a negative error code
809 *
810 * The function is thread-safe when built with the proper option.
811 */
812int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
813{
814	int err = 0;
815
816	assert(pcm);
817	/* FIXME: __snd_pcm_lock() call below is commented out because of the
818	 * the possible deadlock in signal handler calling snd_pcm_abort()
819	 */
820	/* __snd_pcm_lock(pcm->op_arg); */ /* forced lock due to pcm field change */
821	if (pcm->ops->nonblock)
822		err = pcm->ops->nonblock(pcm->op_arg, nonblock);
823	else
824		err = -ENOSYS;
825	if (err < 0)
826		goto unlock;
827	if (nonblock == 2) {
828		pcm->mode |= SND_PCM_ABORT;
829		goto unlock;
830	}
831	if (nonblock)
832		pcm->mode |= SND_PCM_NONBLOCK;
833	else {
834		if (pcm->hw_flags & SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP)
835			err = -EINVAL;
836		else
837			pcm->mode &= ~SND_PCM_NONBLOCK;
838	}
839 unlock:
840	/* __snd_pcm_unlock(pcm->op_arg); */ /* FIXME: see above */
841	return err;
842}
843
844#ifndef DOC_HIDDEN
845/**
846 * \brief set async mode
847 * \param pcm PCM handle
848 * \param sig Signal to raise: < 0 disable, 0 default (SIGIO)
849 * \param pid Process ID to signal: 0 current
850 * \return 0 on success otherwise a negative error code
851 *
852 * A signal is raised every period.
853 */
854int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid)
855{
856	int err = 0;
857
858	assert(pcm);
859	if (sig == 0)
860		sig = SIGIO;
861	if (pid == 0)
862		pid = getpid();
863
864#ifdef THREAD_SAFE_API
865	/* async handler may lead to a deadlock; suppose no multi thread */
866	pcm->lock_enabled = 0;
867#endif
868	if (pcm->ops->async)
869		err = pcm->ops->async(pcm->op_arg, sig, pid);
870	else
871		err = -ENOSYS;
872	return err;
873}
874#endif
875
876/**
877 * \brief Obtain general (static) information for PCM handle
878 * \param pcm PCM handle
879 * \param info Information container
880 * \return 0 on success otherwise a negative error code
881 */
882int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
883{
884	int err = 0;
885
886	assert(pcm && info);
887	if (pcm->ops->info)
888		err = pcm->ops->info(pcm->op_arg, info);
889	else
890		err = -ENOSYS;
891	return err;
892}
893
894/** \brief Retreive current PCM hardware configuration chosen with #snd_pcm_hw_params
895 * \param pcm PCM handle
896 * \param params Configuration space definition container
897 * \return 0 on success otherwise a negative error code
898 * \retval -EBADFD no hardware configuration is set
899 */
900int snd_pcm_hw_params_current(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
901{
902	unsigned int frame_bits;
903
904	assert(pcm && params);
905	if (!pcm->setup)
906		return -EBADFD;
907	memset(params, 0, snd_pcm_hw_params_sizeof());
908	params->flags = pcm->hw_flags;
909	snd_mask_set(&params->masks[SND_PCM_HW_PARAM_ACCESS - SND_PCM_HW_PARAM_FIRST_MASK], pcm->access);
910	snd_mask_set(&params->masks[SND_PCM_HW_PARAM_FORMAT - SND_PCM_HW_PARAM_FIRST_MASK], pcm->format);
911	snd_mask_set(&params->masks[SND_PCM_HW_PARAM_SUBFORMAT - SND_PCM_HW_PARAM_FIRST_MASK], pcm->subformat);
912	frame_bits = snd_pcm_format_physical_width(pcm->format) * pcm->channels;
913	snd_interval_set_value(&params->intervals[SND_PCM_HW_PARAM_FRAME_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL], frame_bits);
914	snd_interval_set_value(&params->intervals[SND_PCM_HW_PARAM_CHANNELS - SND_PCM_HW_PARAM_FIRST_INTERVAL], pcm->channels);
915	snd_interval_set_value(&params->intervals[SND_PCM_HW_PARAM_RATE - SND_PCM_HW_PARAM_FIRST_INTERVAL], pcm->rate);
916	snd_interval_set_value(&params->intervals[SND_PCM_HW_PARAM_PERIOD_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL], pcm->period_time);
917	snd_interval_set_value(&params->intervals[SND_PCM_HW_PARAM_PERIOD_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL], pcm->period_size);
918	snd_interval_copy(&params->intervals[SND_PCM_HW_PARAM_PERIODS - SND_PCM_HW_PARAM_FIRST_INTERVAL], &pcm->periods);
919	snd_interval_copy(&params->intervals[SND_PCM_HW_PARAM_BUFFER_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL], &pcm->buffer_time);
920	snd_interval_set_value(&params->intervals[SND_PCM_HW_PARAM_BUFFER_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL], pcm->buffer_size);
921	snd_interval_set_value(&params->intervals[SND_PCM_HW_PARAM_BUFFER_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL], (pcm->buffer_size * frame_bits) / 8);
922	params->info = pcm->info;
923	params->msbits = pcm->msbits;
924	params->rate_num = pcm->rate_num;
925	params->rate_den = pcm->rate_den;
926	params->fifo_size = pcm->fifo_size;
927	return 0;
928}
929
930/** \brief Install one PCM hardware configuration chosen from a configuration space and #snd_pcm_prepare it
931 * \param pcm PCM handle
932 * \param params Configuration space definition container
933 * \return 0 on success otherwise a negative error code
934 *
935 * The configuration is chosen fixing single parameters in this order:
936 * first access, first format, first subformat, min channels, min rate,
937 * min period time, max buffer size, min tick time. If no mutually
938 * compatible set of parameters can be chosen, a negative error code
939 * will be returned.
940 *
941 * After this call, #snd_pcm_prepare() is called automatically and
942 * the stream is brought to \c #SND_PCM_STATE_PREPARED state.
943 *
944 * The hardware parameters cannot be changed when the stream is
945 * running (active). The software parameters can be changed
946 * at any time.
947 *
948 * The configuration space will be updated to reflect the chosen
949 * parameters.
950 */
951int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
952{
953	int err;
954	assert(pcm && params);
955	err = _snd_pcm_hw_params_internal(pcm, params);
956	if (err < 0)
957		return err;
958	err = snd_pcm_prepare(pcm);
959	return err;
960}
961
962/** \brief Remove PCM hardware configuration and free associated resources
963 * \param pcm PCM handle
964 * \return 0 on success otherwise a negative error code
965 *
966 * The function will also report success if no configuration is set.
967 */
968int snd_pcm_hw_free(snd_pcm_t *pcm)
969{
970	int err;
971	if (! pcm->setup)
972		return 0;
973	if (pcm->mmap_channels) {
974		err = snd_pcm_munmap(pcm);
975		if (err < 0)
976			return err;
977	}
978	// assert(snd_pcm_state(pcm) == SND_PCM_STATE_SETUP ||
979	//        snd_pcm_state(pcm) == SND_PCM_STATE_PREPARED);
980	if (pcm->ops->hw_free)
981		err = pcm->ops->hw_free(pcm->op_arg);
982	else
983		err = -ENOSYS;
984	pcm->setup = 0;
985	if (err < 0)
986		return err;
987	return 0;
988}
989
990/** \brief Install PCM software configuration defined by params
991 * \param pcm PCM handle
992 * \param params Configuration container
993 * \return 0 on success otherwise a negative error code
994 *
995 * The software parameters can be changed at any time.
996 * The hardware parameters cannot be changed when the stream is
997 * running (active).
998 *
999 * The function is thread-safe when built with the proper option.
1000 */
1001int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
1002{
1003	int err;
1004	/* the hw_params must be set at first!!! */
1005	if (CHECK_SANITY(! pcm->setup)) {
1006		SNDMSG("PCM not set up");
1007		return -EIO;
1008	}
1009	if (! params->avail_min) {
1010		SNDMSG("params->avail_min is 0");
1011		return -EINVAL;
1012	}
1013#if 0
1014	/* disable the check below - it looks too restrictive
1015	 * (start_threshold is basically independent from avail_min)
1016	 */
1017	if (params->start_threshold <= pcm->buffer_size &&
1018	    params->start_threshold > (pcm->buffer_size / params->avail_min) * params->avail_min) {
1019		SNDMSG("params->avail_min problem for start_threshold");
1020		return -EINVAL;
1021	}
1022#endif
1023	__snd_pcm_lock(pcm->op_arg); /* forced lock due to pcm field change */
1024	if (pcm->ops->sw_params)
1025		err = pcm->ops->sw_params(pcm->op_arg, params);
1026	else
1027		err = -ENOSYS;
1028	if (err < 0) {
1029		__snd_pcm_unlock(pcm->op_arg);
1030		return err;
1031	}
1032	pcm->tstamp_mode = params->tstamp_mode;
1033	pcm->tstamp_type = params->tstamp_type;
1034	pcm->period_step = params->period_step;
1035	pcm->avail_min = params->avail_min;
1036	pcm->period_event = sw_get_period_event(params);
1037	pcm->start_threshold = params->start_threshold;
1038	pcm->stop_threshold = params->stop_threshold;
1039	pcm->silence_threshold = params->silence_threshold;
1040	pcm->silence_size = params->silence_size;
1041	pcm->boundary = params->boundary;
1042	__snd_pcm_unlock(pcm->op_arg);
1043	return 0;
1044}
1045
1046/**
1047 * \brief Obtain status (runtime) information for PCM handle
1048 * \param pcm PCM handle
1049 * \param status Status container
1050 * \return 0 on success otherwise a negative error code
1051 *
1052 * The function is thread-safe when built with the proper option.
1053 */
1054int snd_pcm_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
1055{
1056	int err;
1057
1058	assert(pcm && status);
1059	snd_pcm_lock(pcm->fast_op_arg);
1060	if (pcm->fast_ops->status)
1061		err = pcm->fast_ops->status(pcm->fast_op_arg, status);
1062	else
1063		err = -ENOSYS;
1064	snd_pcm_unlock(pcm->fast_op_arg);
1065
1066	return err;
1067}
1068
1069/**
1070 * \brief Return PCM state
1071 * \param pcm PCM handle
1072 * \return PCM state #snd_pcm_state_t of given PCM handle
1073 *
1074 * This is a faster way to obtain only the PCM state without calling
1075 * \link ::snd_pcm_status() \endlink.
1076 *
1077 * Note that this function always returns one of the
1078 * #snd_pcm_state_t enum variants.
1079 * It will never return a negative error code.
1080 *
1081 * The function is thread-safe when built with the proper option.
1082 */
1083snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm)
1084{
1085	snd_pcm_state_t state;
1086
1087	assert(pcm);
1088	snd_pcm_lock(pcm->fast_op_arg);
1089	state = __snd_pcm_state(pcm);
1090	snd_pcm_unlock(pcm->fast_op_arg);
1091	return state;
1092}
1093
1094/**
1095 * \brief (DEPRECATED) Synchronize stream position with hardware
1096 * \param pcm PCM handle
1097 * \return 0 on success otherwise a negative error code
1098 *
1099 * Note this function does not update the actual r/w pointer
1100 * for applications. The function #snd_pcm_avail_update()
1101 * have to be called before any mmap begin+commit operation.
1102 *
1103 * The function is thread-safe when built with the proper option.
1104 *
1105 * This function is deprecated. Use #snd_pcm_avail_update() instead.
1106 */
1107int snd_pcm_hwsync(snd_pcm_t *pcm)
1108{
1109	int err;
1110
1111	assert(pcm);
1112	if (CHECK_SANITY(! pcm->setup)) {
1113		SNDMSG("PCM not set up");
1114		return -EIO;
1115	}
1116	snd_pcm_lock(pcm->fast_op_arg);
1117	err = __snd_pcm_hwsync(pcm);
1118	snd_pcm_unlock(pcm->fast_op_arg);
1119	return err;
1120}
1121
1122/**
1123 * \brief Obtain delay for a running PCM handle
1124 * \param pcm PCM handle
1125 * \param delayp Returned delay in frames
1126 * \return 0 on success otherwise a negative error code
1127 *
1128 * For playback the delay is defined as the time that a frame that is written
1129 * to the PCM stream shortly after this call will take to be actually
1130 * audible. It is as such the overall latency from the write call to the final
1131 * DAC.
1132 *
1133 * For capture the delay is defined as the time that a frame that was
1134 * digitized by the audio device takes until it can be read from the PCM
1135 * stream shortly after this call returns. It is as such the overall latency
1136 * from the initial ADC to the read call.
1137 *
1138 * Please note that hence in case of a playback underrun this value will not
1139 * necessarily got down to 0.
1140 *
1141 * If the application is interested in the fill level of the playback buffer
1142 * of the device, it should use #snd_pcm_avail*() functions. The
1143 * value returned by that call is not directly related to the delay, since the
1144 * latter might include some additional, fixed latencies the former does not.
1145 *
1146 * Note this function does not update the actual r/w pointer
1147 * for applications. The function #snd_pcm_avail_update()
1148 * have to be called before any begin+commit operation.
1149 *
1150 * The function is thread-safe when built with the proper option.
1151 */
1152int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
1153{
1154	int err;
1155
1156	assert(pcm);
1157	if (CHECK_SANITY(! pcm->setup)) {
1158		SNDMSG("PCM not set up");
1159		return -EIO;
1160	}
1161	snd_pcm_lock(pcm->fast_op_arg);
1162	err = __snd_pcm_delay(pcm, delayp);
1163	snd_pcm_unlock(pcm->fast_op_arg);
1164	return err;
1165}
1166
1167/**
1168 * \brief Resume from suspend, no samples are lost
1169 * \param pcm PCM handle
1170 * \return 0 on success otherwise a negative error code
1171 * \retval -EAGAIN resume can't be proceed immediately (audio hardware is probably still suspended)
1172 * \retval -ENOSYS hardware doesn't support this feature
1173 *
1174 * This function can be used when the stream is in the suspend state
1175 * to do the fine resume from this state. Not all hardware supports
1176 * this feature, when an -ENOSYS error is returned, use the \link ::snd_pcm_prepare() \endlink
1177 * function to recovery.
1178 *
1179 * The function is thread-safe when built with the proper option.
1180 */
1181int snd_pcm_resume(snd_pcm_t *pcm)
1182{
1183	int err = 0;
1184
1185	assert(pcm);
1186	if (CHECK_SANITY(! pcm->setup)) {
1187		SNDMSG("PCM not set up");
1188		return -EIO;
1189	}
1190	/* lock handled in the callback */
1191	if (pcm->fast_ops->resume)
1192		err = pcm->fast_ops->resume(pcm->fast_op_arg);
1193	else
1194		err = -ENOSYS;
1195	return err;
1196}
1197
1198/**
1199 * \brief Obtain last position update hi-res timestamp
1200 * \param pcm PCM handle
1201 * \param avail Number of available frames when timestamp was grabbed
1202 * \param tstamp Hi-res timestamp
1203 * \return 0 on success otherwise a negative error code
1204 *
1205 * Note this function does not update the actual r/w pointer
1206 * for applications.
1207 *
1208 * The function is thread-safe when built with the proper option.
1209 */
1210int snd_pcm_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail, snd_htimestamp_t *tstamp)
1211{
1212	int err;
1213
1214	assert(pcm);
1215	if (CHECK_SANITY(! pcm->setup)) {
1216		SNDMSG("PCM not set up");
1217		return -EIO;
1218	}
1219	snd_pcm_lock(pcm->fast_op_arg);
1220	if (pcm->fast_ops->htimestamp)
1221		err = pcm->fast_ops->htimestamp(pcm->fast_op_arg, avail, tstamp);
1222	else
1223		err = -ENOSYS;
1224	snd_pcm_unlock(pcm->fast_op_arg);
1225	return err;
1226}
1227
1228/**
1229 * \brief Prepare PCM for use
1230 * \param pcm PCM handle
1231 * \return 0 on success otherwise a negative error code
1232 *
1233 * The function is thread-safe when built with the proper option.
1234 */
1235int snd_pcm_prepare(snd_pcm_t *pcm)
1236{
1237	int err;
1238
1239	assert(pcm);
1240	if (CHECK_SANITY(! pcm->setup)) {
1241		SNDMSG("PCM not set up");
1242		return -EIO;
1243	}
1244	err = bad_pcm_state(pcm, ~P_STATE(DISCONNECTED), 0);
1245	if (err < 0)
1246		return err;
1247	snd_pcm_lock(pcm->fast_op_arg);
1248	if (pcm->fast_ops->prepare)
1249		err = pcm->fast_ops->prepare(pcm->fast_op_arg);
1250	else
1251		err = -ENOSYS;
1252	snd_pcm_unlock(pcm->fast_op_arg);
1253	return err;
1254}
1255
1256/**
1257 * \brief Reset PCM position
1258 * \param pcm PCM handle
1259 * \return 0 on success otherwise a negative error code
1260 *
1261 * Reduce PCM delay to 0.
1262 *
1263 * The function is thread-safe when built with the proper option.
1264 */
1265int snd_pcm_reset(snd_pcm_t *pcm)
1266{
1267	int err;
1268
1269	assert(pcm);
1270	if (CHECK_SANITY(! pcm->setup)) {
1271		SNDMSG("PCM not set up");
1272		return -EIO;
1273	}
1274	snd_pcm_lock(pcm->fast_op_arg);
1275	if (pcm->fast_ops->reset)
1276		err = pcm->fast_ops->reset(pcm->fast_op_arg);
1277	else
1278		err = -ENOSYS;
1279	snd_pcm_unlock(pcm->fast_op_arg);
1280	return err;
1281}
1282
1283/**
1284 * \brief Start a PCM
1285 * \param pcm PCM handle
1286 * \return 0 on success otherwise a negative error code
1287 *
1288 * The function is thread-safe when built with the proper option.
1289 */
1290int snd_pcm_start(snd_pcm_t *pcm)
1291{
1292	int err;
1293
1294	assert(pcm);
1295	if (CHECK_SANITY(! pcm->setup)) {
1296		SNDMSG("PCM not set up");
1297		return -EIO;
1298	}
1299	err = bad_pcm_state(pcm, P_STATE(PREPARED), 0);
1300	if (err < 0)
1301		return err;
1302	snd_pcm_lock(pcm->fast_op_arg);
1303	err = __snd_pcm_start(pcm);
1304	snd_pcm_unlock(pcm->fast_op_arg);
1305	return err;
1306}
1307
1308/**
1309 * \brief Stop a PCM dropping pending frames
1310 * \param pcm PCM handle
1311 * \return 0 on success otherwise a negative error code
1312 *
1313 * This function stops the PCM <i>immediately</i>.
1314 * The pending samples on the buffer are ignored.
1315 *
1316 * For processing all pending samples, use \link ::snd_pcm_drain() \endlink
1317 * instead.
1318 *
1319 * The function is thread-safe when built with the proper option.
1320 */
1321int snd_pcm_drop(snd_pcm_t *pcm)
1322{
1323	int err;
1324
1325	assert(pcm);
1326	if (CHECK_SANITY(! pcm->setup)) {
1327		SNDMSG("PCM not set up");
1328		return -EIO;
1329	}
1330	err = bad_pcm_state(pcm, P_STATE_RUNNABLE | P_STATE(SETUP) |
1331			    P_STATE(SUSPENDED), 0);
1332	if (err < 0)
1333		return err;
1334	snd_pcm_lock(pcm->fast_op_arg);
1335	if (pcm->fast_ops->drop)
1336		err = pcm->fast_ops->drop(pcm->fast_op_arg);
1337	else
1338		err = -ENOSYS;
1339	snd_pcm_unlock(pcm->fast_op_arg);
1340	return err;
1341}
1342
1343/**
1344 * \brief Stop a PCM preserving pending frames
1345 * \param pcm PCM handle
1346 * \return 0 on success otherwise a negative error code
1347 * \retval -ESTRPIPE a suspend event occurred
1348 *
1349 * For playback wait for all pending frames to be played and then stop
1350 * the PCM.
1351 * For capture stop PCM permitting to retrieve residual frames.
1352 *
1353 * For stopping the PCM stream immediately, use \link ::snd_pcm_drop() \endlink
1354 * instead.
1355 *
1356 * The function is thread-safe when built with the proper option.
1357 */
1358int snd_pcm_drain(snd_pcm_t *pcm)
1359{
1360	int err;
1361
1362	assert(pcm);
1363	if (CHECK_SANITY(! pcm->setup)) {
1364		SNDMSG("PCM not set up");
1365		return -EIO;
1366	}
1367	err = bad_pcm_state(pcm, P_STATE_RUNNABLE | P_STATE(SETUP), P_STATE(SETUP));
1368	if (err < 0)
1369		return err;
1370	if (err == 1)
1371		return 0;
1372	/* lock handled in the callback */
1373	if (pcm->fast_ops->drain)
1374		err = pcm->fast_ops->drain(pcm->fast_op_arg);
1375	else
1376		err = -ENOSYS;
1377	return err;
1378}
1379
1380/**
1381 * \brief Pause/resume PCM
1382 * \param pcm PCM handle
1383 * \param enable 0 = resume, 1 = pause
1384 * \return 0 on success otherwise a negative error code
1385 *
1386 * Note that this function works only on the hardware which supports
1387 * pause feature.  You can check it via \link ::snd_pcm_hw_params_can_pause() \endlink
1388 * function.
1389 *
1390 * The function is thread-safe when built with the proper option.
1391 */
1392int snd_pcm_pause(snd_pcm_t *pcm, int enable)
1393{
1394	int err;
1395
1396	assert(pcm);
1397	if (CHECK_SANITY(! pcm->setup)) {
1398		SNDMSG("PCM not set up");
1399		return -EIO;
1400	}
1401	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1402	if (err < 0)
1403		return err;
1404	snd_pcm_lock(pcm->fast_op_arg);
1405	if (pcm->fast_ops->pause)
1406		err = pcm->fast_ops->pause(pcm->fast_op_arg, enable);
1407	else
1408		err = -ENOSYS;
1409	snd_pcm_unlock(pcm->fast_op_arg);
1410	return err;
1411}
1412
1413/**
1414 * \brief Get safe count of frames which can be rewinded
1415 * \param pcm PCM handle
1416 * \return a positive number of frames or negative error code
1417 *
1418 * Note: The snd_pcm_rewind() can accept bigger value than returned
1419 * by this function. But it is not guaranteed that output stream
1420 * will be consistent with bigger value.
1421 *
1422 * The function is thread-safe when built with the proper option.
1423 */
1424snd_pcm_sframes_t snd_pcm_rewindable(snd_pcm_t *pcm)
1425{
1426	snd_pcm_sframes_t result;
1427	int err;
1428
1429	assert(pcm);
1430	if (CHECK_SANITY(! pcm->setup)) {
1431		SNDMSG("PCM not set up");
1432		return -EIO;
1433	}
1434	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1435	if (err < 0)
1436		return err;
1437	snd_pcm_lock(pcm->fast_op_arg);
1438	if (pcm->fast_ops->rewindable)
1439		result = pcm->fast_ops->rewindable(pcm->fast_op_arg);
1440	else
1441		result = -ENOSYS;
1442	snd_pcm_unlock(pcm->fast_op_arg);
1443	return result;
1444}
1445
1446/**
1447 * \brief Move application frame position backward
1448 * \param pcm PCM handle
1449 * \param frames wanted displacement in frames
1450 * \return a positive number for actual displacement otherwise a
1451 * negative error code
1452 *
1453 * The function is thread-safe when built with the proper option.
1454 */
1455snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
1456{
1457	snd_pcm_sframes_t result;
1458	int err;
1459
1460	assert(pcm);
1461	if (CHECK_SANITY(! pcm->setup)) {
1462		SNDMSG("PCM not set up");
1463		return -EIO;
1464	}
1465	if (frames == 0)
1466		return 0;
1467	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1468	if (err < 0)
1469		return err;
1470	snd_pcm_lock(pcm->fast_op_arg);
1471	if (pcm->fast_ops->rewind)
1472		result = pcm->fast_ops->rewind(pcm->fast_op_arg, frames);
1473	else
1474		result = -ENOSYS;
1475	snd_pcm_unlock(pcm->fast_op_arg);
1476	return result;
1477}
1478
1479/**
1480 * \brief Get safe count of frames which can be forwarded
1481 * \param pcm PCM handle
1482 * \return a positive number of frames or negative error code
1483 *
1484 * Note: The snd_pcm_forward() can accept bigger value than returned
1485 * by this function. But it is not guaranteed that output stream
1486 * will be consistent with bigger value.
1487 *
1488 * The function is thread-safe when built with the proper option.
1489 */
1490snd_pcm_sframes_t snd_pcm_forwardable(snd_pcm_t *pcm)
1491{
1492	snd_pcm_sframes_t result;
1493	int err;
1494
1495	assert(pcm);
1496	if (CHECK_SANITY(! pcm->setup)) {
1497		SNDMSG("PCM not set up");
1498		return -EIO;
1499	}
1500	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1501	if (err < 0)
1502		return err;
1503	snd_pcm_lock(pcm->fast_op_arg);
1504	if (pcm->fast_ops->forwardable)
1505		result = pcm->fast_ops->forwardable(pcm->fast_op_arg);
1506	else
1507		result = -ENOSYS;
1508	snd_pcm_unlock(pcm->fast_op_arg);
1509	return result;
1510}
1511
1512/**
1513 * \brief Move application frame position forward
1514 * \param pcm PCM handle
1515 * \param frames wanted skip in frames
1516 * \return a positive number for actual skip otherwise a negative error code
1517 * \retval 0 means no action
1518 *
1519 * The function is thread-safe when built with the proper option.
1520 */
1521#ifndef DOXYGEN
1522EXPORT_SYMBOL snd_pcm_sframes_t INTERNAL(snd_pcm_forward)(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
1523#else
1524snd_pcm_sframes_t snd_pcm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
1525#endif
1526{
1527	snd_pcm_sframes_t result;
1528	int err;
1529
1530	assert(pcm);
1531	if (CHECK_SANITY(! pcm->setup)) {
1532		SNDMSG("PCM not set up");
1533		return -EIO;
1534	}
1535	if (frames == 0)
1536		return 0;
1537	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1538	if (err < 0)
1539		return err;
1540	snd_pcm_lock(pcm->fast_op_arg);
1541	if (pcm->fast_ops->forward)
1542		result = pcm->fast_ops->forward(pcm->fast_op_arg, frames);
1543	else
1544		result = -ENOSYS;
1545	snd_pcm_unlock(pcm->fast_op_arg);
1546	return result;
1547}
1548use_default_symbol_version(__snd_pcm_forward, snd_pcm_forward, ALSA_0.9.0rc8);
1549
1550/**
1551 * \brief Write interleaved frames to a PCM
1552 * \param pcm PCM handle
1553 * \param buffer frames containing buffer
1554 * \param size frames to be written
1555 * \return a positive number of frames actually written otherwise a
1556 * negative error code
1557 * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
1558 * \retval -EPIPE an underrun occurred
1559 * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
1560 *
1561 * If the blocking behaviour is selected and it is running, then routine waits until
1562 * all requested frames are played or put to the playback ring buffer.
1563 * The returned number of frames can be less only if a signal or underrun occurred.
1564 *
1565 * If the non-blocking behaviour is selected, then routine doesn't wait at all.
1566 *
1567 * The function is thread-safe when built with the proper option.
1568 */
1569snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
1570{
1571	int err;
1572
1573	assert(pcm);
1574	assert(size == 0 || buffer);
1575	if (CHECK_SANITY(! pcm->setup)) {
1576		SNDMSG("PCM not set up");
1577		return -EIO;
1578	}
1579	if (pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED) {
1580		SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
1581		return -EINVAL;
1582	}
1583	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1584	if (err < 0)
1585		return err;
1586	return _snd_pcm_writei(pcm, buffer, size);
1587}
1588
1589/**
1590 * \brief Write non interleaved frames to a PCM
1591 * \param pcm PCM handle
1592 * \param bufs frames containing buffers (one for each channel)
1593 * \param size frames to be written
1594 * \return a positive number of frames actually written otherwise a
1595 * negative error code
1596 * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
1597 * \retval -EPIPE an underrun occurred
1598 * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
1599 *
1600 * If the blocking behaviour is selected and it is running, then routine waits until
1601 * all requested frames are played or put to the playback ring buffer.
1602 * The returned number of frames can be less only if a signal or underrun occurred.
1603 *
1604 * If the non-blocking behaviour is selected, then routine doesn't wait at all.
1605 *
1606 * The function is thread-safe when built with the proper option.
1607 */
1608snd_pcm_sframes_t snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
1609{
1610	int err;
1611
1612	assert(pcm);
1613	assert(size == 0 || bufs);
1614	if (CHECK_SANITY(! pcm->setup)) {
1615		SNDMSG("PCM not set up");
1616		return -EIO;
1617	}
1618	if (pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
1619		SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
1620		return -EINVAL;
1621	}
1622	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1623	if (err < 0)
1624		return err;
1625	return _snd_pcm_writen(pcm, bufs, size);
1626}
1627
1628/**
1629 * \brief Read interleaved frames from a PCM
1630 * \param pcm PCM handle
1631 * \param buffer frames containing buffer
1632 * \param size frames to be read
1633 * \return a positive number of frames actually read otherwise a
1634 * negative error code
1635 * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
1636 * \retval -EPIPE an overrun occurred
1637 * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
1638 *
1639 * If the blocking behaviour was selected and it is running, then routine waits until
1640 * all requested frames are filled. The returned number of frames can be less only
1641 * if a signal or underrun occurred.
1642 *
1643 * If the non-blocking behaviour is selected, then routine doesn't wait at all.
1644 *
1645 * The function is thread-safe when built with the proper option.
1646 */
1647snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
1648{
1649	int err;
1650
1651	assert(pcm);
1652	assert(size == 0 || buffer);
1653	if (CHECK_SANITY(! pcm->setup)) {
1654		SNDMSG("PCM not set up");
1655		return -EIO;
1656	}
1657	if (pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED) {
1658		SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
1659		return -EINVAL;
1660	}
1661	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1662	if (err < 0)
1663		return err;
1664	return _snd_pcm_readi(pcm, buffer, size);
1665}
1666
1667/**
1668 * \brief Read non interleaved frames to a PCM
1669 * \param pcm PCM handle
1670 * \param bufs frames containing buffers (one for each channel)
1671 * \param size frames to be read
1672 * \return a positive number of frames actually read otherwise a
1673 * negative error code
1674 * \retval -EBADFD PCM is not in the right state (#SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING)
1675 * \retval -EPIPE an overrun occurred
1676 * \retval -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
1677 *
1678 * If the blocking behaviour was selected and it is running, then routine waits until
1679 * all requested frames are filled. The returned number of frames can be less only
1680 * if a signal or underrun occurred.
1681 *
1682 * If the non-blocking behaviour is selected, then routine doesn't wait at all.
1683 *
1684 * The function is thread-safe when built with the proper option.
1685 */
1686snd_pcm_sframes_t snd_pcm_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
1687{
1688	int err;
1689
1690	assert(pcm);
1691	assert(size == 0 || bufs);
1692	if (CHECK_SANITY(! pcm->setup)) {
1693		SNDMSG("PCM not set up");
1694		return -EIO;
1695	}
1696	if (pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
1697		SNDMSG("invalid access type %s", snd_pcm_access_name(pcm->access));
1698		return -EINVAL;
1699	}
1700	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
1701	if (err < 0)
1702		return err;
1703	return _snd_pcm_readn(pcm, bufs, size);
1704}
1705
1706/**
1707 * \brief Link two PCMs
1708 * \param pcm1 first PCM handle
1709 * \param pcm2 first PCM handle
1710 * \return 0 on success otherwise a negative error code
1711 *
1712 * The two PCMs will start/stop/prepare in sync.
1713 */
1714int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
1715{
1716	int err = 0;
1717
1718	assert(pcm1);
1719	assert(pcm2);
1720	if (pcm1->fast_ops->link)
1721		err = pcm1->fast_ops->link(pcm1->fast_op_arg, pcm2);
1722	else
1723		err = -ENOSYS;
1724	return err;
1725}
1726
1727/**
1728 * \brief Remove a PCM from a linked group
1729 * \param pcm PCM handle
1730 * \return 0 on success otherwise a negative error code
1731 */
1732int snd_pcm_unlink(snd_pcm_t *pcm)
1733{
1734	int err = 0;
1735
1736	assert(pcm);
1737	if (pcm->fast_ops->unlink)
1738		err = pcm->fast_ops->unlink(pcm->fast_op_arg);
1739	else
1740		err = -ENOSYS;
1741	return err;
1742}
1743
1744/* locked version */
1745static int __snd_pcm_poll_descriptors_count(snd_pcm_t *pcm)
1746{
1747	if (pcm->fast_ops->poll_descriptors_count)
1748		return pcm->fast_ops->poll_descriptors_count(pcm->fast_op_arg);
1749	return pcm->poll_fd_count;
1750}
1751
1752/**
1753 * \brief get count of poll descriptors for PCM handle
1754 * \param pcm PCM handle
1755 * \return count of poll descriptors
1756 *
1757 * The function is thread-safe when built with the proper option.
1758 */
1759int snd_pcm_poll_descriptors_count(snd_pcm_t *pcm)
1760{
1761	int count;
1762
1763	assert(pcm);
1764	snd_pcm_lock(pcm->fast_op_arg);
1765	count = __snd_pcm_poll_descriptors_count(pcm);
1766	snd_pcm_unlock(pcm->fast_op_arg);
1767	return count;
1768}
1769
1770/* locked version */
1771static int __snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
1772				      unsigned int space)
1773{
1774	if (pcm->fast_ops->poll_descriptors)
1775		return pcm->fast_ops->poll_descriptors(pcm->fast_op_arg, pfds, space);
1776	if (pcm->poll_fd < 0) {
1777		SNDMSG("poll_fd < 0");
1778		return -EIO;
1779	}
1780	if (space >= 1 && pfds) {
1781		pfds->fd = pcm->poll_fd;
1782		pfds->events = pcm->poll_events | POLLERR | POLLNVAL;
1783	} else {
1784		return 0;
1785	}
1786	return 1;
1787}
1788
1789/**
1790 * \brief get poll descriptors
1791 * \param pcm PCM handle
1792 * \param pfds array of poll descriptors
1793 * \param space space in the poll descriptor array
1794 * \return count of filled descriptors
1795 *
1796 * This function fills the given poll descriptor structs for the specified
1797 * PCM handle.  The poll desctiptor array should have the size returned by
1798 * \link ::snd_pcm_poll_descriptors_count() \endlink function.
1799 *
1800 * The result is intended for direct use with the poll() syscall.
1801 *
1802 * For reading the returned events of poll descriptor after poll() system
1803 * call, use \link ::snd_pcm_poll_descriptors_revents() \endlink function.
1804 * The field values in pollfd structs may be bogus regarding the stream
1805 * direction from the application perspective (POLLIN might not imply read
1806 * direction and POLLOUT might not imply write), but
1807 * the \link ::snd_pcm_poll_descriptors_revents() \endlink function
1808 * does the right "demangling".
1809 *
1810 * You can use output from this function as arguments for the select()
1811 * syscall, too. Do not forget to translate POLLIN and POLLOUT events to
1812 * corresponding FD_SET arrays and demangle events using
1813 * \link ::snd_pcm_poll_descriptors_revents() \endlink .
1814 *
1815 * It is guaranteed that for the given PCM handle, the output poll
1816 * descriptor structs (and their count) will not change after
1817 * hardware and software parameters setup. Thus it is valid to call
1818 * the function once when all parameters are set and reuse its output
1819 * for the lifetime of the stream parameters.
1820 *
1821 * The function is thread-safe when built with the proper option.
1822 */
1823int snd_pcm_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
1824{
1825	int err;
1826
1827	assert(pcm && pfds);
1828	snd_pcm_lock(pcm->fast_op_arg);
1829	err = __snd_pcm_poll_descriptors(pcm, pfds, space);
1830	snd_pcm_unlock(pcm->fast_op_arg);
1831	return err;
1832}
1833
1834static int __snd_pcm_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds,
1835				  unsigned int nfds, unsigned short *revents);
1836
1837/**
1838 * \brief get returned events from poll descriptors
1839 * \param pcm PCM handle
1840 * \param pfds array of poll descriptors
1841 * \param nfds count of poll descriptors
1842 * \param revents pointer to the returned (single) event
1843 * \return zero if success, otherwise a negative error code
1844 *
1845 * This function does "demangling" of the revents mask returned from
1846 * the poll() syscall to correct semantics (POLLIN = read, POLLOUT = write).
1847 *
1848 * Note: The null event also exists. Even if poll() or select()
1849 * syscall returned that some events are waiting, this function might
1850 * return empty set of events. In this case, application should
1851 * do next event waiting using poll() or select().
1852 *
1853 * Note: Even if multiple poll descriptors are used (i.e. pfds > 1),
1854 * this function returns only a single event.
1855 *
1856 * The passed in count of poll descriptors must be equal to
1857 * \link ::snd_pcm_poll_descriptors_count() \endlink and the passed in array
1858 * must match the array returned by \link ::snd_pcm_poll_descriptors() \endlink
1859 * (in its full length and original order) with the revent fields updated
1860 * according to the poll() result. This function will not modify the file
1861 * descriptor or event field of any element of the given poll descriptor array.
1862 *
1863 * The function is thread-safe when built with the proper option.
1864 */
1865int snd_pcm_poll_descriptors_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
1866{
1867	int err;
1868
1869	assert(pcm && pfds && revents);
1870	snd_pcm_lock(pcm->fast_op_arg);
1871	err = __snd_pcm_poll_revents(pcm, pfds, nfds, revents);
1872	snd_pcm_unlock(pcm->fast_op_arg);
1873	return err;
1874}
1875
1876static int __snd_pcm_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds,
1877				  unsigned int nfds, unsigned short *revents)
1878{
1879	if (pcm->fast_ops->poll_revents)
1880		return pcm->fast_ops->poll_revents(pcm->fast_op_arg, pfds, nfds, revents);
1881	if (nfds == 1) {
1882		*revents = pfds->revents;
1883		return 0;
1884	}
1885	return -EINVAL;
1886}
1887
1888#ifndef DOC_HIDDEN
1889#define PCMTYPE(v) [SND_PCM_TYPE_##v] = #v
1890#define STATE(v) [SND_PCM_STATE_##v] = #v
1891#define STREAM(v) [SND_PCM_STREAM_##v] = #v
1892#define READY(v) [SND_PCM_READY_##v] = #v
1893#define XRUN(v) [SND_PCM_XRUN_##v] = #v
1894#define SILENCE(v) [SND_PCM_SILENCE_##v] = #v
1895#define TSTAMP(v) [SND_PCM_TSTAMP_##v] = #v
1896#define TSTAMP_TYPE(v) [SND_PCM_TSTAMP_TYPE_##v] = #v
1897#define ACCESS(v) [SND_PCM_ACCESS_##v] = #v
1898#define START(v) [SND_PCM_START_##v] = #v
1899#define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v
1900#define SW_PARAM(v) [SND_PCM_SW_PARAM_##v] = #v
1901#define FORMAT(v) [SND_PCM_FORMAT_##v] = #v
1902#define SUBFORMAT(v) [SND_PCM_SUBFORMAT_##v] = #v
1903
1904#define FORMATD(v, d) [SND_PCM_FORMAT_##v] = d
1905#define SUBFORMATD(v, d) [SND_PCM_SUBFORMAT_##v] = d
1906
1907
1908static const char *const snd_pcm_stream_names[] = {
1909	STREAM(PLAYBACK),
1910	STREAM(CAPTURE),
1911};
1912
1913static const char *const snd_pcm_state_names[] = {
1914	STATE(OPEN),
1915	STATE(SETUP),
1916	STATE(PREPARED),
1917	STATE(RUNNING),
1918	STATE(XRUN),
1919	STATE(DRAINING),
1920	STATE(PAUSED),
1921	STATE(SUSPENDED),
1922	STATE(DISCONNECTED),
1923};
1924
1925static const char *const snd_pcm_access_names[] = {
1926	ACCESS(MMAP_INTERLEAVED),
1927	ACCESS(MMAP_NONINTERLEAVED),
1928	ACCESS(MMAP_COMPLEX),
1929	ACCESS(RW_INTERLEAVED),
1930	ACCESS(RW_NONINTERLEAVED),
1931};
1932
1933static const char *const snd_pcm_format_names[] = {
1934	FORMAT(S8),
1935	FORMAT(U8),
1936	FORMAT(S16_LE),
1937	FORMAT(S16_BE),
1938	FORMAT(U16_LE),
1939	FORMAT(U16_BE),
1940	FORMAT(S24_LE),
1941	FORMAT(S24_BE),
1942	FORMAT(U24_LE),
1943	FORMAT(U24_BE),
1944	FORMAT(S32_LE),
1945	FORMAT(S32_BE),
1946	FORMAT(U32_LE),
1947	FORMAT(U32_BE),
1948	FORMAT(FLOAT_LE),
1949	FORMAT(FLOAT_BE),
1950	FORMAT(FLOAT64_LE),
1951	FORMAT(FLOAT64_BE),
1952	FORMAT(IEC958_SUBFRAME_LE),
1953	FORMAT(IEC958_SUBFRAME_BE),
1954	FORMAT(MU_LAW),
1955	FORMAT(A_LAW),
1956	FORMAT(IMA_ADPCM),
1957	FORMAT(MPEG),
1958	FORMAT(GSM),
1959	FORMAT(S20_LE),
1960	FORMAT(S20_BE),
1961	FORMAT(U20_LE),
1962	FORMAT(U20_BE),
1963	FORMAT(SPECIAL),
1964	FORMAT(S24_3LE),
1965	FORMAT(S24_3BE),
1966	FORMAT(U24_3LE),
1967	FORMAT(U24_3BE),
1968	FORMAT(S20_3LE),
1969	FORMAT(S20_3BE),
1970	FORMAT(U20_3LE),
1971	FORMAT(U20_3BE),
1972	FORMAT(S18_3LE),
1973	FORMAT(S18_3BE),
1974	FORMAT(U18_3LE),
1975	FORMAT(U18_3BE),
1976	FORMAT(G723_24),
1977	FORMAT(G723_24_1B),
1978	FORMAT(G723_40),
1979	FORMAT(G723_40_1B),
1980	FORMAT(DSD_U8),
1981	FORMAT(DSD_U16_LE),
1982	FORMAT(DSD_U32_LE),
1983	FORMAT(DSD_U16_BE),
1984	FORMAT(DSD_U32_BE),
1985};
1986
1987static const char *const snd_pcm_format_aliases[SND_PCM_FORMAT_LAST+1] = {
1988	FORMAT(S16),
1989	FORMAT(U16),
1990	FORMAT(S24),
1991	FORMAT(U24),
1992	FORMAT(S32),
1993	FORMAT(U32),
1994	FORMAT(FLOAT),
1995	FORMAT(FLOAT64),
1996	FORMAT(IEC958_SUBFRAME),
1997	FORMAT(S20),
1998	FORMAT(U20),
1999};
2000
2001static const char *const snd_pcm_format_descriptions[] = {
2002	FORMATD(S8, "Signed 8 bit"),
2003	FORMATD(U8, "Unsigned 8 bit"),
2004	FORMATD(S16_LE, "Signed 16 bit Little Endian"),
2005	FORMATD(S16_BE, "Signed 16 bit Big Endian"),
2006	FORMATD(U16_LE, "Unsigned 16 bit Little Endian"),
2007	FORMATD(U16_BE, "Unsigned 16 bit Big Endian"),
2008	FORMATD(S24_LE, "Signed 24 bit Little Endian"),
2009	FORMATD(S24_BE, "Signed 24 bit Big Endian"),
2010	FORMATD(U24_LE, "Unsigned 24 bit Little Endian"),
2011	FORMATD(U24_BE, "Unsigned 24 bit Big Endian"),
2012	FORMATD(S32_LE, "Signed 32 bit Little Endian"),
2013	FORMATD(S32_BE, "Signed 32 bit Big Endian"),
2014	FORMATD(U32_LE, "Unsigned 32 bit Little Endian"),
2015	FORMATD(U32_BE, "Unsigned 32 bit Big Endian"),
2016	FORMATD(FLOAT_LE, "Float 32 bit Little Endian"),
2017	FORMATD(FLOAT_BE, "Float 32 bit Big Endian"),
2018	FORMATD(FLOAT64_LE, "Float 64 bit Little Endian"),
2019	FORMATD(FLOAT64_BE, "Float 64 bit Big Endian"),
2020	FORMATD(IEC958_SUBFRAME_LE, "IEC-958 Little Endian"),
2021	FORMATD(IEC958_SUBFRAME_BE, "IEC-958 Big Endian"),
2022	FORMATD(MU_LAW, "Mu-Law"),
2023	FORMATD(A_LAW, "A-Law"),
2024	FORMATD(IMA_ADPCM, "Ima-ADPCM"),
2025	FORMATD(MPEG, "MPEG"),
2026	FORMATD(GSM, "GSM"),
2027	FORMATD(S20_LE, "Signed 20 bit Little Endian in 4 bytes, LSB justified"),
2028	FORMATD(S20_BE, "Signed 20 bit Big Endian in 4 bytes, LSB justified"),
2029	FORMATD(U20_LE, "Unsigned 20 bit Little Endian in 4 bytes, LSB justified"),
2030	FORMATD(U20_BE, "Unsigned 20 bit Big Endian in 4 bytes, LSB justified"),
2031	FORMATD(SPECIAL, "Special"),
2032	FORMATD(S24_3LE, "Signed 24 bit Little Endian in 3bytes"),
2033	FORMATD(S24_3BE, "Signed 24 bit Big Endian in 3bytes"),
2034	FORMATD(U24_3LE, "Unsigned 24 bit Little Endian in 3bytes"),
2035	FORMATD(U24_3BE, "Unsigned 24 bit Big Endian in 3bytes"),
2036	FORMATD(S20_3LE, "Signed 20 bit Little Endian in 3bytes"),
2037	FORMATD(S20_3BE, "Signed 20 bit Big Endian in 3bytes"),
2038	FORMATD(U20_3LE, "Unsigned 20 bit Little Endian in 3bytes"),
2039	FORMATD(U20_3BE, "Unsigned 20 bit Big Endian in 3bytes"),
2040	FORMATD(S18_3LE, "Signed 18 bit Little Endian in 3bytes"),
2041	FORMATD(S18_3BE, "Signed 18 bit Big Endian in 3bytes"),
2042	FORMATD(U18_3LE, "Unsigned 18 bit Little Endian in 3bytes"),
2043	FORMATD(U18_3BE, "Unsigned 18 bit Big Endian in 3bytes"),
2044	FORMATD(G723_24, "G.723 (ADPCM) 24 kbit/s, 8 samples in 3 bytes"),
2045	FORMATD(G723_24_1B, "G.723 (ADPCM) 24 kbit/s, 1 sample in 1 byte"),
2046	FORMATD(G723_40, "G.723 (ADPCM) 40 kbit/s, 8 samples in 3 bytes"),
2047	FORMATD(G723_40_1B, "G.723 (ADPCM) 40 kbit/s, 1 sample in 1 byte"),
2048	FORMATD(DSD_U8,  "Direct Stream Digital, 1-byte (x8), oldest bit in MSB"),
2049	FORMATD(DSD_U16_LE, "Direct Stream Digital, 2-byte (x16), little endian, oldest bits in MSB"),
2050	FORMATD(DSD_U32_LE, "Direct Stream Digital, 4-byte (x32), little endian, oldest bits in MSB"),
2051	FORMATD(DSD_U16_BE, "Direct Stream Digital, 2-byte (x16), big endian, oldest bits in MSB"),
2052	FORMATD(DSD_U32_BE, "Direct Stream Digital, 4-byte (x32), big endian, oldest bits in MSB"),
2053};
2054
2055static const char *const snd_pcm_type_names[] = {
2056	PCMTYPE(HW),
2057	PCMTYPE(HOOKS),
2058	PCMTYPE(MULTI),
2059	PCMTYPE(FILE),
2060	PCMTYPE(NULL),
2061	PCMTYPE(SHM),
2062	PCMTYPE(INET),
2063	PCMTYPE(COPY),
2064	PCMTYPE(LINEAR),
2065	PCMTYPE(ALAW),
2066	PCMTYPE(MULAW),
2067	PCMTYPE(ADPCM),
2068	PCMTYPE(RATE),
2069	PCMTYPE(ROUTE),
2070	PCMTYPE(PLUG),
2071	PCMTYPE(SHARE),
2072	PCMTYPE(METER),
2073	PCMTYPE(MIX),
2074	PCMTYPE(DROUTE),
2075	PCMTYPE(LBSERVER),
2076	PCMTYPE(LINEAR_FLOAT),
2077	PCMTYPE(LADSPA),
2078	PCMTYPE(DMIX),
2079	PCMTYPE(JACK),
2080	PCMTYPE(DSNOOP),
2081	PCMTYPE(IEC958),
2082	PCMTYPE(SOFTVOL),
2083	PCMTYPE(IOPLUG),
2084	PCMTYPE(EXTPLUG),
2085	PCMTYPE(MMAP_EMUL),
2086};
2087
2088static const char *const snd_pcm_subformat_names[] = {
2089	SUBFORMAT(STD),
2090	SUBFORMAT(MSBITS_MAX),
2091	SUBFORMAT(MSBITS_20),
2092	SUBFORMAT(MSBITS_24),
2093};
2094
2095static const char *const snd_pcm_subformat_descriptions[] = {
2096	SUBFORMATD(STD, "Standard"),
2097	SUBFORMATD(MSBITS_MAX, "Maximum based on PCM format"),
2098	SUBFORMATD(MSBITS_20, "20 most significant bits"),
2099	SUBFORMATD(MSBITS_24, "24 most significant bits"),
2100};
2101
2102static const char *const snd_pcm_start_mode_names[] = {
2103	START(EXPLICIT),
2104	START(DATA),
2105};
2106
2107static const char *const snd_pcm_xrun_mode_names[] = {
2108	XRUN(NONE),
2109	XRUN(STOP),
2110};
2111
2112static const char *const snd_pcm_tstamp_mode_names[] = {
2113	TSTAMP(NONE),
2114	TSTAMP(ENABLE),
2115};
2116
2117static const char *const snd_pcm_tstamp_type_names[] = {
2118	TSTAMP_TYPE(GETTIMEOFDAY),
2119	TSTAMP_TYPE(MONOTONIC),
2120	TSTAMP_TYPE(MONOTONIC_RAW),
2121};
2122#endif
2123
2124/**
2125 * \brief get name of PCM stream type
2126 * \param stream PCM stream type
2127 * \return ascii name of PCM stream type
2128 */
2129const char *snd_pcm_stream_name(const snd_pcm_stream_t stream)
2130{
2131	if (stream > SND_PCM_STREAM_LAST)
2132		return NULL;
2133	return snd_pcm_stream_names[stream];
2134}
2135
2136/**
2137 * \brief get name of PCM access type
2138 * \param acc PCM access type
2139 * \return ascii name of PCM access type
2140 */
2141const char *snd_pcm_access_name(const snd_pcm_access_t acc)
2142{
2143	if (acc > SND_PCM_ACCESS_LAST)
2144		return NULL;
2145	return snd_pcm_access_names[acc];
2146}
2147
2148/**
2149 * \brief get name of PCM sample format
2150 * \param format PCM sample format
2151 * \return ascii name of PCM sample format
2152 */
2153const char *snd_pcm_format_name(const snd_pcm_format_t format)
2154{
2155	if (format > SND_PCM_FORMAT_LAST)
2156		return NULL;
2157	return snd_pcm_format_names[format];
2158}
2159
2160/**
2161 * \brief get description of PCM sample format
2162 * \param format PCM sample format
2163 * \return ascii description of PCM sample format
2164 */
2165const char *snd_pcm_format_description(const snd_pcm_format_t format)
2166{
2167	if (format > SND_PCM_FORMAT_LAST)
2168		return NULL;
2169	return snd_pcm_format_descriptions[format];
2170}
2171
2172/**
2173 * \brief get PCM sample format from name
2174 * \param name PCM sample format name (case insensitive)
2175 * \return PCM sample format
2176 */
2177snd_pcm_format_t snd_pcm_format_value(const char* name)
2178{
2179	snd_pcm_format_t format;
2180	for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
2181		if (snd_pcm_format_names[format] &&
2182		    strcasecmp(name, snd_pcm_format_names[format]) == 0) {
2183			return format;
2184		}
2185		if (snd_pcm_format_aliases[format] &&
2186		    strcasecmp(name, snd_pcm_format_aliases[format]) == 0) {
2187			return format;
2188		}
2189	}
2190	for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
2191		if (snd_pcm_format_descriptions[format] &&
2192		    strcasecmp(name, snd_pcm_format_descriptions[format]) == 0) {
2193			return format;
2194		}
2195	}
2196	return SND_PCM_FORMAT_UNKNOWN;
2197}
2198
2199/**
2200 * \brief get name of PCM sample subformat
2201 * \param subformat PCM sample subformat
2202 * \return ascii name of PCM sample subformat
2203 */
2204const char *snd_pcm_subformat_name(const snd_pcm_subformat_t subformat)
2205{
2206	if (subformat > SND_PCM_SUBFORMAT_LAST)
2207		return NULL;
2208	return snd_pcm_subformat_names[subformat];
2209}
2210
2211/**
2212 * \brief get description of PCM sample subformat
2213 * \param subformat PCM sample subformat
2214 * \return ascii description of PCM sample subformat
2215 */
2216const char *snd_pcm_subformat_description(const snd_pcm_subformat_t subformat)
2217{
2218	if (subformat > SND_PCM_SUBFORMAT_LAST)
2219		return NULL;
2220	return snd_pcm_subformat_descriptions[subformat];
2221}
2222
2223/**
2224 * \brief get PCM sample subformat from name
2225 * \param name PCM sample subformat name (case insensitive)
2226 * \return PCM sample subformat
2227 */
2228snd_pcm_subformat_t snd_pcm_subformat_value(const char* name)
2229{
2230	snd_pcm_subformat_t subformat;
2231
2232	for (subformat = 0; subformat <= SND_PCM_SUBFORMAT_LAST; subformat++) {
2233		if (snd_pcm_subformat_names[subformat] &&
2234		    !strcasecmp(name, snd_pcm_subformat_names[subformat]))
2235			return subformat;
2236	}
2237
2238	for (subformat = 0; subformat <= SND_PCM_SUBFORMAT_LAST; subformat++) {
2239		if (snd_pcm_subformat_descriptions[subformat] &&
2240		    !strcasecmp(name, snd_pcm_subformat_descriptions[subformat]))
2241			return subformat;
2242	}
2243
2244	return SND_PCM_SUBFORMAT_UNKNOWN;
2245}
2246
2247/**
2248 * \brief (DEPRECATED) get name of PCM start mode setting
2249 * \param mode PCM start mode
2250 * \return ascii name of PCM start mode setting
2251 */
2252const char *snd_pcm_start_mode_name(snd_pcm_start_t mode)
2253{
2254	if (mode > SND_PCM_START_LAST)
2255		return NULL;
2256	return snd_pcm_start_mode_names[mode];
2257}
2258
2259#ifndef DOC_HIDDEN
2260link_warning(snd_pcm_start_mode_name, "Warning: start_mode is deprecated, consider to use start_threshold");
2261#endif
2262
2263/**
2264 * \brief (DEPRECATED) get name of PCM xrun mode setting
2265 * \param mode PCM xrun mode
2266 * \return ascii name of PCM xrun mode setting
2267 */
2268const char *snd_pcm_xrun_mode_name(snd_pcm_xrun_t mode)
2269{
2270	if (mode > SND_PCM_XRUN_LAST)
2271		return NULL;
2272	return snd_pcm_xrun_mode_names[mode];
2273}
2274
2275#ifndef DOC_HIDDEN
2276link_warning(snd_pcm_xrun_mode_name, "Warning: xrun_mode is deprecated, consider to use stop_threshold");
2277#endif
2278
2279/**
2280 * \brief get name of PCM tstamp mode setting
2281 * \param mode PCM tstamp mode
2282 * \return ascii name of PCM tstamp mode setting
2283 */
2284const char *snd_pcm_tstamp_mode_name(const snd_pcm_tstamp_t mode)
2285{
2286	if (mode > SND_PCM_TSTAMP_LAST)
2287		return NULL;
2288	return snd_pcm_tstamp_mode_names[mode];
2289}
2290
2291/**
2292 * \brief get name of PCM tstamp type setting
2293 * \param type PCM tstamp type
2294 * \return ascii name of PCM tstamp type setting
2295 */
2296const char *snd_pcm_tstamp_type_name(snd_pcm_tstamp_type_t type)
2297{
2298	if (type > SND_PCM_TSTAMP_TYPE_LAST)
2299		return NULL;
2300	return snd_pcm_tstamp_type_names[type];
2301}
2302
2303/**
2304 * \brief get name of PCM state
2305 * \param state PCM state
2306 * \return ascii name of PCM state
2307 */
2308const char *snd_pcm_state_name(const snd_pcm_state_t state)
2309{
2310	if (state > SND_PCM_STATE_LAST)
2311		return NULL;
2312	return snd_pcm_state_names[state];
2313}
2314
2315/**
2316 * \brief get name of PCM type
2317 * \param type PCM type
2318 * \return ascii name of PCM type
2319 */
2320#ifndef DOXYGEN
2321EXPORT_SYMBOL const char *INTERNAL(snd_pcm_type_name)(snd_pcm_type_t type)
2322#else
2323const char *snd_pcm_type_name(snd_pcm_type_t type)
2324#endif
2325{
2326	if (type > SND_PCM_TYPE_LAST)
2327		return NULL;
2328	return snd_pcm_type_names[type];
2329}
2330use_default_symbol_version(__snd_pcm_type_name, snd_pcm_type_name, ALSA_0.9.0);
2331
2332/**
2333 * \brief Dump current hardware setup for PCM
2334 * \param pcm PCM handle
2335 * \param out Output handle
2336 * \return 0 on success otherwise a negative error code
2337 */
2338int snd_pcm_dump_hw_setup(snd_pcm_t *pcm, snd_output_t *out)
2339{
2340	assert(pcm);
2341	assert(out);
2342	if (CHECK_SANITY(! pcm->setup)) {
2343		SNDMSG("PCM not set up");
2344		return -EIO;
2345	}
2346        snd_output_printf(out, "  stream       : %s\n", snd_pcm_stream_name(pcm->stream));
2347	snd_output_printf(out, "  access       : %s\n", snd_pcm_access_name(pcm->access));
2348	snd_output_printf(out, "  format       : %s\n", snd_pcm_format_name(pcm->format));
2349	snd_output_printf(out, "  subformat    : %s\n", snd_pcm_subformat_name(pcm->subformat));
2350	snd_output_printf(out, "  channels     : %u\n", pcm->channels);
2351	snd_output_printf(out, "  rate         : %u\n", pcm->rate);
2352	snd_output_printf(out, "  exact rate   : %g (%u/%u)\n",
2353			  (pcm->rate_den ? ((double) pcm->rate_num / pcm->rate_den) : 0.0),
2354			  pcm->rate_num, pcm->rate_den);
2355	snd_output_printf(out, "  msbits       : %u\n", pcm->msbits);
2356	snd_output_printf(out, "  buffer_size  : %lu\n", pcm->buffer_size);
2357	snd_output_printf(out, "  period_size  : %lu\n", pcm->period_size);
2358	snd_output_printf(out, "  period_time  : %u\n", pcm->period_time);
2359	return 0;
2360}
2361
2362/**
2363 * \brief Dump current software setup for PCM
2364 * \param pcm PCM handle
2365 * \param out Output handle
2366 * \return 0 on success otherwise a negative error code
2367 */
2368int snd_pcm_dump_sw_setup(snd_pcm_t *pcm, snd_output_t *out)
2369{
2370	assert(pcm);
2371	assert(out);
2372	if (CHECK_SANITY(! pcm->setup)) {
2373		SNDMSG("PCM not set up");
2374		return -EIO;
2375	}
2376	snd_output_printf(out, "  tstamp_mode  : %s\n", snd_pcm_tstamp_mode_name(pcm->tstamp_mode));
2377	snd_output_printf(out, "  tstamp_type  : %s\n", snd_pcm_tstamp_type_name(pcm->tstamp_type));
2378	snd_output_printf(out, "  period_step  : %d\n", pcm->period_step);
2379	snd_output_printf(out, "  avail_min    : %ld\n", pcm->avail_min);
2380	snd_output_printf(out, "  period_event : %i\n", pcm->period_event);
2381	snd_output_printf(out, "  start_threshold  : %ld\n", pcm->start_threshold);
2382	snd_output_printf(out, "  stop_threshold   : %ld\n", pcm->stop_threshold);
2383	snd_output_printf(out, "  silence_threshold: %ld\n", pcm->silence_threshold);
2384	snd_output_printf(out, "  silence_size : %ld\n", pcm->silence_size);
2385	snd_output_printf(out, "  boundary     : %ld\n", pcm->boundary);
2386	return 0;
2387}
2388
2389/**
2390 * \brief Dump current setup (hardware and software) for PCM
2391 * \param pcm PCM handle
2392 * \param out Output handle
2393 * \return 0 on success otherwise a negative error code
2394 */
2395int snd_pcm_dump_setup(snd_pcm_t *pcm, snd_output_t *out)
2396{
2397	snd_pcm_dump_hw_setup(pcm, out);
2398	snd_pcm_dump_sw_setup(pcm, out);
2399	return 0;
2400}
2401
2402/**
2403 * \brief Dump status
2404 * \param status Status container
2405 * \param out Output handle
2406 * \return 0 on success otherwise a negative error code
2407 */
2408int snd_pcm_status_dump(snd_pcm_status_t *status, snd_output_t *out)
2409{
2410	assert(status);
2411	snd_output_printf(out, "  state       : %s\n", snd_pcm_state_name((snd_pcm_state_t) status->state));
2412	snd_output_printf(out, "  trigger_time: %ld.%06ld\n",
2413			  status->trigger_tstamp.tv_sec,
2414			  status->trigger_tstamp.tv_nsec / 1000);
2415	snd_output_printf(out, "  tstamp      : %ld.%06ld\n",
2416		status->tstamp.tv_sec, status->tstamp.tv_nsec / 1000);
2417	snd_output_printf(out, "  delay       : %ld\n", (long)status->delay);
2418	snd_output_printf(out, "  avail       : %ld\n", (long)status->avail);
2419	snd_output_printf(out, "  avail_max   : %ld\n", (long)status->avail_max);
2420	return 0;
2421}
2422
2423/**
2424 * \brief Dump PCM info
2425 * \param pcm PCM handle
2426 * \param out Output handle
2427 * \return 0 on success otherwise a negative error code
2428 */
2429int snd_pcm_dump(snd_pcm_t *pcm, snd_output_t *out)
2430{
2431	int err = 0;
2432
2433	assert(pcm);
2434	assert(out);
2435	if (pcm->ops->dump)
2436		pcm->ops->dump(pcm->op_arg, out);
2437	else
2438		err = -ENOSYS;
2439	return err;
2440}
2441
2442/**
2443 * \brief Convert bytes in frames for a PCM
2444 * \param pcm PCM handle
2445 * \param bytes quantity in bytes
2446 * \return quantity expressed in frames
2447 */
2448snd_pcm_sframes_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes)
2449{
2450	assert(pcm);
2451	if (CHECK_SANITY(! pcm->setup)) {
2452		SNDMSG("PCM not set up");
2453		return -EIO;
2454	}
2455	return bytes * 8 / pcm->frame_bits;
2456}
2457
2458/**
2459 * \brief Convert frames in bytes for a PCM
2460 * \param pcm PCM handle
2461 * \param frames quantity in frames
2462 * \return quantity expressed in bytes
2463 */
2464ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, snd_pcm_sframes_t frames)
2465{
2466	assert(pcm);
2467	if (CHECK_SANITY(! pcm->setup)) {
2468		SNDMSG("PCM not set up");
2469		return -EIO;
2470	}
2471	return frames * pcm->frame_bits / 8;
2472}
2473
2474/**
2475 * \brief Convert bytes in samples for a PCM
2476 * \param pcm PCM handle
2477 * \param bytes quantity in bytes
2478 * \return quantity expressed in samples
2479 */
2480long snd_pcm_bytes_to_samples(snd_pcm_t *pcm, ssize_t bytes)
2481{
2482	assert(pcm);
2483	if (CHECK_SANITY(! pcm->setup)) {
2484		SNDMSG("PCM not set up");
2485		return -EIO;
2486	}
2487	return bytes * 8 / pcm->sample_bits;
2488}
2489
2490/**
2491 * \brief Convert samples in bytes for a PCM
2492 * \param pcm PCM handle
2493 * \param samples quantity in samples
2494 * \return quantity expressed in bytes
2495 */
2496ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, long samples)
2497{
2498	assert(pcm);
2499	if (CHECK_SANITY(! pcm->setup)) {
2500		SNDMSG("PCM not set up");
2501		return -EIO;
2502	}
2503	return samples * pcm->sample_bits / 8;
2504}
2505
2506/**
2507 * \brief Add an async handler for a PCM
2508 * \param handler Returned handler handle
2509 * \param pcm PCM handle
2510 * \param callback Callback function
2511 * \param private_data Callback private data
2512 * \return 0 otherwise a negative error code on failure
2513 *
2514 * The asynchronous callback is called when period boundary elapses.
2515 */
2516int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm,
2517			      snd_async_callback_t callback, void *private_data)
2518{
2519	int err;
2520	int was_empty;
2521	snd_async_handler_t *h;
2522	err = snd_async_add_handler(&h, _snd_pcm_async_descriptor(pcm),
2523				    callback, private_data);
2524	if (err < 0)
2525		return err;
2526	h->type = SND_ASYNC_HANDLER_PCM;
2527	h->u.pcm = pcm;
2528	was_empty = list_empty(&pcm->async_handlers);
2529	list_add_tail(&h->hlist, &pcm->async_handlers);
2530	if (was_empty) {
2531		err = snd_pcm_async(pcm, snd_async_handler_get_signo(h), getpid());
2532		if (err < 0) {
2533			snd_async_del_handler(h);
2534			return err;
2535		}
2536	}
2537	*handler = h;
2538	return 0;
2539}
2540
2541/**
2542 * \brief Return PCM handle related to an async handler
2543 * \param handler Async handler handle
2544 * \return PCM handle
2545 */
2546snd_pcm_t *snd_async_handler_get_pcm(snd_async_handler_t *handler)
2547{
2548	if (handler->type != SND_ASYNC_HANDLER_PCM) {
2549		SNDMSG("invalid handler type %d", handler->type);
2550		return NULL;
2551	}
2552	return handler->u.pcm;
2553}
2554
2555static const char *const build_in_pcms[] = {
2556	"adpcm", "alaw", "copy", "dmix", "file", "hooks", "hw", "ladspa", "lfloat",
2557	"linear", "meter", "mulaw", "multi", "null", "empty", "plug", "rate", "route", "share",
2558	"shm", "dsnoop", "dshare", "asym", "iec958", "softvol", "mmap_emul",
2559	NULL
2560};
2561
2562static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
2563			     snd_config_t *pcm_root, snd_config_t *pcm_conf,
2564			     snd_pcm_stream_t stream, int mode)
2565{
2566	const char *str;
2567	char *buf = NULL, *buf1 = NULL;
2568	int err;
2569	snd_config_t *conf, *type_conf = NULL, *tmp;
2570	snd_config_iterator_t i, next;
2571	const char *id;
2572	const char *lib = NULL, *open_name = NULL;
2573	int (*open_func)(snd_pcm_t **, const char *,
2574			 snd_config_t *, snd_config_t *,
2575			 snd_pcm_stream_t, int) = NULL;
2576#ifndef PIC
2577	extern void *snd_pcm_open_symbols(void);
2578#endif
2579	if (snd_config_get_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) {
2580		char *val;
2581		id = NULL;
2582		snd_config_get_id(pcm_conf, &id);
2583		val = NULL;
2584		snd_config_get_ascii(pcm_conf, &val);
2585		SNDERR("Invalid type for PCM %s%sdefinition (id: %s, value: %s)", name ? name : "", name ? " " : "", id, val);
2586		free(val);
2587		return -EINVAL;
2588	}
2589	err = snd_config_search(pcm_conf, "type", &conf);
2590	if (err < 0) {
2591		SNDERR("type is not defined");
2592		return err;
2593	}
2594	err = snd_config_get_id(conf, &id);
2595	if (err < 0) {
2596		SNDERR("unable to get id");
2597		return err;
2598	}
2599	err = snd_config_get_string(conf, &str);
2600	if (err < 0) {
2601		SNDERR("Invalid type for %s", id);
2602		return err;
2603	}
2604	err = snd_config_search_definition(pcm_root, "pcm_type", str, &type_conf);
2605	if (err >= 0) {
2606		if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
2607			SNDERR("Invalid type for PCM type %s definition", str);
2608			err = -EINVAL;
2609			goto _err;
2610		}
2611		snd_config_for_each(i, next, type_conf) {
2612			snd_config_t *n = snd_config_iterator_entry(i);
2613			const char *id;
2614			if (snd_config_get_id(n, &id) < 0)
2615				continue;
2616			if (strcmp(id, "comment") == 0)
2617				continue;
2618			if (strcmp(id, "lib") == 0) {
2619				err = snd_config_get_string(n, &lib);
2620				if (err < 0) {
2621					SNDERR("Invalid type for %s", id);
2622					goto _err;
2623				}
2624				continue;
2625			}
2626			if (strcmp(id, "open") == 0) {
2627				err = snd_config_get_string(n, &open_name);
2628				if (err < 0) {
2629					SNDERR("Invalid type for %s", id);
2630					goto _err;
2631				}
2632				continue;
2633			}
2634			SNDERR("Unknown field %s", id);
2635			err = -EINVAL;
2636			goto _err;
2637		}
2638	}
2639	if (!open_name) {
2640		buf = malloc(strlen(str) + 32);
2641		if (buf == NULL) {
2642			err = -ENOMEM;
2643			goto _err;
2644		}
2645		open_name = buf;
2646		sprintf(buf, "_snd_pcm_%s_open", str);
2647	}
2648	if (!lib) {
2649		const char *const *build_in = build_in_pcms;
2650		while (*build_in) {
2651			if (!strcmp(*build_in, str))
2652				break;
2653			build_in++;
2654		}
2655		if (*build_in == NULL) {
2656			buf1 = malloc(strlen(str) + 32);
2657			if (buf1 == NULL) {
2658				err = -ENOMEM;
2659				goto _err;
2660			}
2661			lib = buf1;
2662			sprintf(buf1, "libasound_module_pcm_%s.so", str);
2663		}
2664	}
2665#ifndef PIC
2666	snd_pcm_open_symbols();	/* this call is for static linking only */
2667#endif
2668	open_func = snd_dlobj_cache_get(lib, open_name,
2669			SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION), 1);
2670	if (open_func) {
2671		err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode);
2672		if (err >= 0) {
2673			if ((*pcmp)->open_func) {
2674				/* only init plugin (like empty, asym) */
2675				snd_dlobj_cache_put(open_func);
2676			} else {
2677				(*pcmp)->open_func = open_func;
2678			}
2679			err = 0;
2680		} else {
2681			snd_dlobj_cache_put(open_func);
2682		}
2683	} else {
2684		err = -ENXIO;
2685	}
2686	if (err >= 0) {
2687		err = snd_config_search(pcm_root, "defaults.pcm.compat", &tmp);
2688		if (err >= 0) {
2689			long i;
2690			if (snd_config_get_integer(tmp, &i) >= 0) {
2691				if (i > 0)
2692					(*pcmp)->compat = 1;
2693			}
2694		} else {
2695			char *str = getenv("LIBASOUND_COMPAT");
2696			if (str && *str)
2697				(*pcmp)->compat = 1;
2698		}
2699		err = snd_config_search(pcm_root, "defaults.pcm.minperiodtime", &tmp);
2700		if (err >= 0)
2701			snd_config_get_integer(tmp, &(*pcmp)->minperiodtime);
2702		err = 0;
2703	}
2704       _err:
2705	if (type_conf)
2706		snd_config_delete(type_conf);
2707	free(buf);
2708	free(buf1);
2709	return err;
2710}
2711
2712static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
2713				 const char *name, snd_pcm_stream_t stream,
2714				 int mode, int hop)
2715{
2716	int err;
2717	snd_config_t *pcm_conf;
2718	const char *str;
2719
2720	err = snd_config_search_definition(root, "pcm", name, &pcm_conf);
2721	if (err < 0) {
2722		SNDERR("Unknown PCM %s", name);
2723		return err;
2724	}
2725	if (snd_config_get_string(pcm_conf, &str) >= 0)
2726		err = snd_pcm_open_noupdate(pcmp, root, str, stream, mode,
2727					    hop + 1);
2728	else {
2729		snd_config_set_hop(pcm_conf, hop);
2730		err = snd_pcm_open_conf(pcmp, name, root, pcm_conf, stream, mode);
2731	}
2732	snd_config_delete(pcm_conf);
2733	return err;
2734}
2735
2736/**
2737 * \brief Opens a PCM
2738 * \param pcmp Returned PCM handle
2739 * \param name ASCII identifier of the PCM handle
2740 * \param stream Wanted stream
2741 * \param mode Open mode (see #SND_PCM_NONBLOCK, #SND_PCM_ASYNC)
2742 * \return 0 on success otherwise a negative error code
2743 */
2744int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
2745		 snd_pcm_stream_t stream, int mode)
2746{
2747	snd_config_t *top;
2748	int err;
2749
2750	assert(pcmp && name);
2751	if (_snd_is_ucm_device(name)) {
2752		name = uc_mgr_alibcfg_by_device(&top, name);
2753		if (name == NULL)
2754			return -ENODEV;
2755	} else {
2756		err = snd_config_update_ref(&top);
2757		if (err < 0)
2758			return err;
2759	}
2760	err = snd_pcm_open_noupdate(pcmp, top, name, stream, mode, 0);
2761	snd_config_unref(top);
2762	return err;
2763}
2764
2765/**
2766 * \brief Opens a PCM using local configuration
2767 * \param pcmp Returned PCM handle
2768 * \param name ASCII identifier of the PCM handle
2769 * \param stream Wanted stream
2770 * \param mode Open mode (see #SND_PCM_NONBLOCK, #SND_PCM_ASYNC)
2771 * \param lconf Local configuration
2772 * \return 0 on success otherwise a negative error code
2773 */
2774int snd_pcm_open_lconf(snd_pcm_t **pcmp, const char *name,
2775		       snd_pcm_stream_t stream, int mode,
2776		       snd_config_t *lconf)
2777{
2778	assert(pcmp && name && lconf);
2779	return snd_pcm_open_noupdate(pcmp, lconf, name, stream, mode, 0);
2780}
2781
2782/**
2783 * \brief Opens a fallback PCM
2784 * \param pcmp Returned PCM handle
2785 * \param root Configuration root
2786 * \param name ASCII identifier of the PCM handle
2787 * \param orig_name The original ASCII name
2788 * \param stream Wanted stream
2789 * \param mode Open mode (see #SND_PCM_NONBLOCK, #SND_PCM_ASYNC)
2790 * \return 0 on success otherwise a negative error code
2791 */
2792int snd_pcm_open_fallback(snd_pcm_t **pcmp, snd_config_t *root,
2793			  const char *name, const char *orig_name,
2794			  snd_pcm_stream_t stream, int mode)
2795{
2796	int err;
2797	assert(pcmp && name && root);
2798	err = snd_pcm_open_noupdate(pcmp, root, name, stream, mode, 0);
2799	if (err >= 0) {
2800		free((*pcmp)->name);
2801		(*pcmp)->name = orig_name ? strdup(orig_name) : NULL;
2802	}
2803	return err;
2804}
2805
2806#ifndef DOC_HIDDEN
2807int snd_pcm_new(snd_pcm_t **pcmp, snd_pcm_type_t type, const char *name,
2808		snd_pcm_stream_t stream, int mode)
2809{
2810	snd_pcm_t *pcm;
2811#ifdef THREAD_SAFE_API
2812	pthread_mutexattr_t attr;
2813#endif
2814
2815	pcm = calloc(1, sizeof(*pcm));
2816	if (!pcm)
2817		return -ENOMEM;
2818	pcm->type = type;
2819	if (name)
2820		pcm->name = strdup(name);
2821	pcm->stream = stream;
2822	pcm->mode = mode;
2823	pcm->poll_fd_count = 1;
2824	pcm->poll_fd = -1;
2825	pcm->op_arg = pcm;
2826	pcm->fast_op_arg = pcm;
2827	INIT_LIST_HEAD(&pcm->async_handlers);
2828#ifdef THREAD_SAFE_API
2829	pthread_mutexattr_init(&attr);
2830#ifdef HAVE_PTHREAD_MUTEX_RECURSIVE
2831	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
2832#endif
2833	pthread_mutex_init(&pcm->lock, &attr);
2834	pthread_mutexattr_destroy(&attr);
2835	/* use locking as default;
2836	 * each plugin may suppress this in its open call
2837	 */
2838	pcm->need_lock = 1;
2839	if (mode & SND_PCM_ASYNC) {
2840		/* async handler may lead to a deadlock; suppose no MT */
2841		pcm->lock_enabled = 0;
2842	} else {
2843		/* set lock_enabled field depending on $LIBASOUND_THREAD_SAFE */
2844		static int do_lock_enable = -1; /* uninitialized */
2845
2846		/* evaluate env var only once at the first open for consistency */
2847		if (do_lock_enable == -1) {
2848			char *p = getenv("LIBASOUND_THREAD_SAFE");
2849			do_lock_enable = !p || *p != '0';
2850		}
2851		pcm->lock_enabled = do_lock_enable;
2852	}
2853#endif
2854	*pcmp = pcm;
2855	return 0;
2856}
2857
2858int snd_pcm_free(snd_pcm_t *pcm)
2859{
2860	assert(pcm);
2861	free(pcm->name);
2862	free(pcm->hw.link_dst);
2863	free(pcm->appl.link_dst);
2864	snd_dlobj_cache_put(pcm->open_func);
2865#ifdef THREAD_SAFE_API
2866	pthread_mutex_destroy(&pcm->lock);
2867#endif
2868	free(pcm);
2869	return 0;
2870}
2871
2872int snd_pcm_open_named_slave(snd_pcm_t **pcmp, const char *name,
2873			     snd_config_t *root,
2874			     snd_config_t *conf, snd_pcm_stream_t stream,
2875			     int mode, snd_config_t *parent_conf)
2876{
2877	const char *str;
2878	int hop;
2879
2880	if ((hop = snd_config_check_hop(parent_conf)) < 0)
2881		return hop;
2882	if (snd_config_get_string(conf, &str) >= 0)
2883		return snd_pcm_open_noupdate(pcmp, root, str, stream, mode,
2884					     hop + 1);
2885	return snd_pcm_open_conf(pcmp, name, root, conf, stream, mode);
2886}
2887#endif
2888
2889/**
2890 * \brief Wait for a PCM to become ready
2891 * \param pcm PCM handle
2892 * \param timeout maximum time in milliseconds to wait,
2893 *        a -1 value means infinity (SND_PCM_WAIT_INFINITE),
2894 *	       see also SND_PCM_WAIT_IO and SND_PCM_WAIT_DRAIN
2895 * \return a positive value on success otherwise a negative error code
2896 *         (-EPIPE for the xrun and -ESTRPIPE for the suspended status,
2897 *          others for general errors)
2898 * \retval 0 timeout occurred
2899 * \retval 1 PCM stream is ready for I/O
2900 *
2901 * The function is thread-safe when built with the proper option.
2902 */
2903int snd_pcm_wait(snd_pcm_t *pcm, int timeout)
2904{
2905	int err;
2906
2907	__snd_pcm_lock(pcm->fast_op_arg); /* forced lock */
2908	err = __snd_pcm_wait_in_lock(pcm, timeout);
2909	__snd_pcm_unlock(pcm->fast_op_arg);
2910	return err;
2911}
2912
2913#ifndef DOC_HIDDEN
2914/* locked version */
2915int __snd_pcm_wait_in_lock(snd_pcm_t *pcm, int timeout)
2916{
2917	int err;
2918
2919	/* NOTE: avail_min check can be skipped during draining */
2920	if (__snd_pcm_state(pcm) != SND_PCM_STATE_DRAINING &&
2921	    !snd_pcm_may_wait_for_avail_min(pcm, snd_pcm_mmap_avail(pcm))) {
2922		/* check more precisely */
2923		err = pcm_state_to_error(__snd_pcm_state(pcm));
2924		return err < 0 ? err : 1;
2925	}
2926	return snd_pcm_wait_nocheck(pcm, timeout);
2927}
2928
2929static int __snd_pcm_wait_io_timeout(snd_pcm_t *pcm)
2930{
2931	int timeout;
2932
2933	/* period size is the time boundary */
2934	timeout = (pcm->period_size * 1000ULL) / pcm->rate;
2935	/* should not happen */
2936	if (timeout < 0)
2937		timeout = 0;
2938	/* add extra time of 200 milliseconds */
2939	timeout += 200;
2940	return timeout;
2941}
2942
2943static int __snd_pcm_wait_drain_timeout(snd_pcm_t *pcm)
2944{
2945	int timeout;
2946
2947	/* for capture, there's no reason to wait, just one iteration */
2948	if (snd_pcm_stream(pcm) == SND_PCM_STREAM_CAPTURE)
2949		return 0;
2950	/* result is in milliseconds */
2951	timeout = (snd_pcm_mmap_playback_delay(pcm) * 1000LL) / pcm->rate;
2952	/* should not happen */
2953	if (timeout < 0)
2954		timeout = 0;
2955	/* add extra time of 200 milliseconds */
2956	timeout += 200;
2957	return timeout;
2958}
2959
2960/*
2961 * like snd_pcm_wait() but doesn't check mmap_avail before calling poll()
2962 *
2963 * used in drain code in some plugins
2964 *
2965 * This function is called inside pcm lock.
2966 */
2967int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout)
2968{
2969	struct pollfd *pfd;
2970	unsigned short revents = 0;
2971	int npfds, err, err_poll;
2972
2973	npfds = __snd_pcm_poll_descriptors_count(pcm);
2974	if (npfds <= 0 || npfds >= 16) {
2975		SNDERR("Invalid poll_fds %d", npfds);
2976		return -EIO;
2977	}
2978	pfd = alloca(sizeof(*pfd) * npfds);
2979	err = __snd_pcm_poll_descriptors(pcm, pfd, npfds);
2980	if (err < 0)
2981		return err;
2982	if (err != npfds) {
2983		SNDMSG("invalid poll descriptors %d", err);
2984		return -EIO;
2985	}
2986	if (timeout == SND_PCM_WAIT_IO)
2987		timeout = __snd_pcm_wait_io_timeout(pcm);
2988	else if (timeout == SND_PCM_WAIT_DRAIN)
2989		timeout = __snd_pcm_wait_drain_timeout(pcm);
2990	else if (timeout < -1)
2991		SNDMSG("invalid snd_pcm_wait timeout argument %d", timeout);
2992	do {
2993		__snd_pcm_unlock(pcm->fast_op_arg);
2994		err_poll = poll(pfd, npfds, timeout);
2995		__snd_pcm_lock(pcm->fast_op_arg);
2996		if (err_poll < 0) {
2997			if (errno == EINTR && !PCMINABORT(pcm) && !(pcm->mode & SND_PCM_EINTR))
2998		                continue;
2999			return -errno;
3000                }
3001		if (! err_poll)
3002			break;
3003		err = __snd_pcm_poll_revents(pcm, pfd, npfds, &revents);
3004		if (err < 0)
3005			return err;
3006		if (revents & (POLLERR | POLLNVAL)) {
3007			/* check more precisely */
3008			err = pcm_state_to_error(__snd_pcm_state(pcm));
3009			return err < 0 ? err : -EIO;
3010		}
3011	} while (!(revents & (POLLIN | POLLOUT)));
3012#if 0 /* very useful code to test poll related problems */
3013	{
3014		snd_pcm_sframes_t avail_update;
3015		__snd_pcm_hwsync(pcm);
3016		avail_update = __snd_pcm_avail_update(pcm);
3017		if (avail_update < (snd_pcm_sframes_t)pcm->avail_min) {
3018			printf("*** snd_pcm_wait() FATAL ERROR!!!\n");
3019			printf("avail_min = %li, avail_update = %li\n", pcm->avail_min, avail_update);
3020		}
3021	}
3022#endif
3023	return err_poll > 0 ? 1 : 0;
3024}
3025#endif
3026
3027/**
3028 * \brief Return number of frames ready to be read (capture) / written (playback)
3029 * \param pcm PCM handle
3030 * \return a positive number of frames ready otherwise a negative
3031 * error code
3032 *
3033 * On capture does all the actions needed to transport to application
3034 * level all the ready frames across underlying layers.
3035 *
3036 * The position is not synced with hardware (driver) position in the sound
3037 * ring buffer in this function. This function is a light version of
3038 * #snd_pcm_avail() .
3039 *
3040 * Using this function is ideal after poll() or select() when audio
3041 * file descriptor made the event and when application expects just period
3042 * timing.
3043 *
3044 * Also this function might be called after #snd_pcm_delay() or
3045 * #snd_pcm_hwsync() functions to move private ring buffer pointers
3046 * in alsa-lib (the internal plugin chain).
3047 *
3048 * The function is thread-safe when built with the proper option.
3049 */
3050snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm)
3051{
3052	snd_pcm_sframes_t result;
3053
3054	snd_pcm_lock(pcm->fast_op_arg);
3055	result = __snd_pcm_avail_update(pcm);
3056	snd_pcm_unlock(pcm->fast_op_arg);
3057	return result;
3058}
3059
3060/**
3061 * \brief Return number of frames ready to be read (capture) / written (playback)
3062 * \param pcm PCM handle
3063 * \return a positive number of frames ready otherwise a negative
3064 * error code
3065 *
3066 * On capture does all the actions needed to transport to application
3067 * level all the ready frames across underlying layers.
3068 *
3069 * The position is synced with hardware (driver) position in the sound
3070 * ring buffer in this functions.
3071 *
3072 * The function is thread-safe when built with the proper option.
3073 */
3074snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t *pcm)
3075{
3076	int err;
3077	snd_pcm_sframes_t result;
3078
3079	assert(pcm);
3080	if (CHECK_SANITY(! pcm->setup)) {
3081		SNDMSG("PCM not set up");
3082		return -EIO;
3083	}
3084	snd_pcm_lock(pcm->fast_op_arg);
3085	err = __snd_pcm_hwsync(pcm);
3086	if (err < 0)
3087		result = err;
3088	else
3089		result = __snd_pcm_avail_update(pcm);
3090	snd_pcm_unlock(pcm->fast_op_arg);
3091	return result;
3092}
3093
3094/**
3095 * \brief Combine snd_pcm_avail and snd_pcm_delay functions
3096 * \param pcm PCM handle
3097 * \param availp Number of available frames in the ring buffer
3098 * \param delayp Total I/O latency in frames
3099 * \return zero on success otherwise a negative error code
3100 *
3101 * The avail and delay values retuned are in sync.
3102 *
3103 * The function is thread-safe when built with the proper option.
3104 */
3105int snd_pcm_avail_delay(snd_pcm_t *pcm,
3106			snd_pcm_sframes_t *availp,
3107			snd_pcm_sframes_t *delayp)
3108{
3109	snd_pcm_sframes_t sf;
3110	int err;
3111
3112	assert(pcm && availp && delayp);
3113	if (CHECK_SANITY(! pcm->setup)) {
3114		SNDMSG("PCM not set up");
3115		return -EIO;
3116	}
3117	snd_pcm_lock(pcm->fast_op_arg);
3118	err = __snd_pcm_hwsync(pcm);
3119	if (err < 0)
3120		goto unlock;
3121	sf = __snd_pcm_avail_update(pcm);
3122	if (sf < 0) {
3123		err = (int)sf;
3124		goto unlock;
3125	}
3126	err = __snd_pcm_delay(pcm, delayp);
3127	if (err < 0)
3128		goto unlock;
3129	*availp = sf;
3130	err = 0;
3131 unlock:
3132	snd_pcm_unlock(pcm->fast_op_arg);
3133	return err;
3134}
3135
3136/**
3137 * \brief Silence an area
3138 * \param dst_area area specification
3139 * \param dst_offset offset in frames inside area
3140 * \param samples samples to silence
3141 * \param format PCM sample format
3142 * \return 0 on success otherwise a negative error code
3143 */
3144int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t dst_offset,
3145			 unsigned int samples, snd_pcm_format_t format)
3146{
3147	/* FIXME: sub byte resolution and odd dst_offset */
3148	char *dst;
3149	unsigned int dst_step;
3150	int width;
3151	uint64_t silence;
3152	if (!dst_area->addr)
3153		return 0;
3154	dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
3155	width = snd_pcm_format_physical_width(format);
3156	silence = snd_pcm_format_silence_64(format);
3157        /*
3158         * Iterate copying silent sample for sample data aligned to 64 bit.
3159         * This is a fast path.
3160         */
3161        if (dst_area->step == (unsigned int) width &&
3162            width != 24 &&
3163            ((intptr_t)dst & 7) == 0) {
3164		unsigned int dwords = samples * width / 64;
3165		uint64_t *dstp = (uint64_t *)dst;
3166		samples -= dwords * 64 / width;
3167		while (dwords-- > 0)
3168			*dstp++ = silence;
3169		if (samples == 0)
3170			return 0;
3171		dst = (char *)dstp;
3172	}
3173	dst_step = dst_area->step / 8;
3174	switch (width) {
3175	case 4: {
3176		uint8_t s0 = silence & 0xf0;
3177		uint8_t s1 = silence & 0x0f;
3178		int dstbit = dst_area->first % 8;
3179		int dstbit_step = dst_area->step % 8;
3180		while (samples-- > 0) {
3181			if (dstbit) {
3182				*dst &= 0xf0;
3183				*dst |= s1;
3184			} else {
3185				*dst &= 0x0f;
3186				*dst |= s0;
3187			}
3188			dst += dst_step;
3189			dstbit += dstbit_step;
3190			if (dstbit == 8) {
3191				dst++;
3192				dstbit = 0;
3193			}
3194		}
3195		break;
3196	}
3197	case 8: {
3198		uint8_t sil = silence;
3199		while (samples-- > 0) {
3200			*dst = sil;
3201			dst += dst_step;
3202		}
3203		break;
3204	}
3205	case 16: {
3206		uint16_t sil = silence;
3207		while (samples-- > 0) {
3208			*(uint16_t*)dst = sil;
3209			dst += dst_step;
3210		}
3211		break;
3212	}
3213	case 24: {
3214		while (samples-- > 0) {
3215#ifdef SNDRV_LITTLE_ENDIAN
3216			*(dst + 0) = silence >> 0;
3217			*(dst + 1) = silence >> 8;
3218			*(dst + 2) = silence >> 16;
3219#else
3220			*(dst + 2) = silence >> 0;
3221			*(dst + 1) = silence >> 8;
3222			*(dst + 0) = silence >> 16;
3223#endif
3224			dst += dst_step;
3225		}
3226	}
3227		break;
3228	case 32: {
3229		uint32_t sil = silence;
3230		while (samples-- > 0) {
3231			*(uint32_t*)dst = sil;
3232			dst += dst_step;
3233		}
3234		break;
3235	}
3236	case 64: {
3237		while (samples-- > 0) {
3238			*(uint64_t*)dst = silence;
3239			dst += dst_step;
3240		}
3241		break;
3242	}
3243	default:
3244		SNDMSG("invalid format width %d", width);
3245		return -EINVAL;
3246	}
3247	return 0;
3248}
3249
3250/**
3251 * \brief Silence one or more areas
3252 * \param dst_areas areas specification (one for each channel)
3253 * \param dst_offset offset in frames inside area
3254 * \param channels channels count
3255 * \param frames frames to silence
3256 * \param format PCM sample format
3257 * \return 0 on success otherwise a negative error code
3258 */
3259int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
3260			  unsigned int channels, snd_pcm_uframes_t frames, snd_pcm_format_t format)
3261{
3262	int width = snd_pcm_format_physical_width(format);
3263	while (channels > 0) {
3264		void *addr = dst_areas->addr;
3265		unsigned int step = dst_areas->step;
3266		const snd_pcm_channel_area_t *begin = dst_areas;
3267		int channels1 = channels;
3268		unsigned int chns = 0;
3269		int err;
3270		while (1) {
3271			channels1--;
3272			chns++;
3273			dst_areas++;
3274			if (channels1 == 0 ||
3275			    dst_areas->addr != addr ||
3276			    dst_areas->step != step ||
3277			    dst_areas->first != dst_areas[-1].first + width)
3278				break;
3279		}
3280		if (chns > 1 && chns * width == step) {
3281			/* Collapse the areas */
3282			snd_pcm_channel_area_t d;
3283			d.addr = begin->addr;
3284			d.first = begin->first;
3285			d.step = width;
3286			err = snd_pcm_area_silence(&d, dst_offset * chns, frames * chns, format);
3287			channels -= chns;
3288		} else {
3289			err = snd_pcm_area_silence(begin, dst_offset, frames, format);
3290			dst_areas = begin + 1;
3291			channels--;
3292		}
3293		if (err < 0)
3294			return err;
3295	}
3296	return 0;
3297}
3298
3299
3300/**
3301 * \brief Copy an area
3302 * \param dst_area destination area specification
3303 * \param dst_offset offset in frames inside destination area
3304 * \param src_area source area specification
3305 * \param src_offset offset in frames inside source area
3306 * \param samples samples to copy
3307 * \param format PCM sample format
3308 * \return 0 on success otherwise a negative error code
3309 */
3310int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t dst_offset,
3311		      const snd_pcm_channel_area_t *src_area, snd_pcm_uframes_t src_offset,
3312		      unsigned int samples, snd_pcm_format_t format)
3313{
3314	/* FIXME: sub byte resolution and odd dst_offset */
3315	const char *src;
3316	char *dst;
3317	int width;
3318	int src_step, dst_step;
3319	if (dst_area == src_area && dst_offset == src_offset)
3320		return 0;
3321	if (!src_area->addr)
3322		return snd_pcm_area_silence(dst_area, dst_offset, samples, format);
3323	src = snd_pcm_channel_area_addr(src_area, src_offset);
3324	if (!dst_area->addr)
3325		return 0;
3326	dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
3327	width = snd_pcm_format_physical_width(format);
3328	if (src_area->step == (unsigned int) width &&
3329	    dst_area->step == (unsigned int) width) {
3330		size_t bytes = samples * width / 8;
3331		samples -= bytes * 8 / width;
3332		assert(src < dst || src >= dst + bytes);
3333		assert(dst < src || dst >= src + bytes);
3334		memcpy(dst, src, bytes);
3335		if (samples == 0)
3336			return 0;
3337	}
3338	src_step = src_area->step / 8;
3339	dst_step = dst_area->step / 8;
3340	switch (width) {
3341	case 4: {
3342		int srcbit = src_area->first % 8;
3343		int srcbit_step = src_area->step % 8;
3344		int dstbit = dst_area->first % 8;
3345		int dstbit_step = dst_area->step % 8;
3346		while (samples-- > 0) {
3347			unsigned char srcval;
3348			if (srcbit)
3349				srcval = *src & 0x0f;
3350			else
3351				srcval = *src & 0xf0;
3352			if (dstbit)
3353				*dst &= 0xf0;
3354			else
3355				*dst &= 0x0f;
3356			*dst |= srcval;
3357			src += src_step;
3358			srcbit += srcbit_step;
3359			if (srcbit == 8) {
3360				src++;
3361				srcbit = 0;
3362			}
3363			dst += dst_step;
3364			dstbit += dstbit_step;
3365			if (dstbit == 8) {
3366				dst++;
3367				dstbit = 0;
3368			}
3369		}
3370		break;
3371	}
3372	case 8: {
3373		while (samples-- > 0) {
3374			*dst = *src;
3375			src += src_step;
3376			dst += dst_step;
3377		}
3378		break;
3379	}
3380	case 16: {
3381		while (samples-- > 0) {
3382			*(uint16_t*)dst = *(const uint16_t*)src;
3383			src += src_step;
3384			dst += dst_step;
3385		}
3386		break;
3387	}
3388	case 24:
3389		while (samples-- > 0) {
3390			*(dst + 0) = *(src + 0);
3391			*(dst + 1) = *(src + 1);
3392			*(dst + 2) = *(src + 2);
3393			src += src_step;
3394			dst += dst_step;
3395		}
3396		break;
3397	case 32: {
3398		while (samples-- > 0) {
3399			*(uint32_t*)dst = *(const uint32_t*)src;
3400			src += src_step;
3401			dst += dst_step;
3402		}
3403		break;
3404	}
3405	case 64: {
3406		while (samples-- > 0) {
3407			*(uint64_t*)dst = *(const uint64_t*)src;
3408			src += src_step;
3409			dst += dst_step;
3410		}
3411		break;
3412	}
3413	default:
3414		SNDMSG("invalid format width %d", width);
3415		return -EINVAL;
3416	}
3417	return 0;
3418}
3419
3420/**
3421 * \brief Copy one or more areas
3422 * \param dst_areas destination areas specification (one for each channel)
3423 * \param dst_offset offset in frames inside destination area
3424 * \param src_areas source areas specification (one for each channel)
3425 * \param src_offset offset in frames inside source area
3426 * \param channels channels count
3427 * \param frames frames to copy
3428 * \param format PCM sample format
3429 * \return 0 on success otherwise a negative error code
3430 */
3431int snd_pcm_areas_copy(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,
3432		       const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,
3433		       unsigned int channels, snd_pcm_uframes_t frames, snd_pcm_format_t format)
3434{
3435	int width = snd_pcm_format_physical_width(format);
3436	assert(dst_areas);
3437	assert(src_areas);
3438	if (! channels) {
3439		SNDMSG("invalid channels %d", channels);
3440		return -EINVAL;
3441	}
3442	if (! frames) {
3443		SNDMSG("invalid frames %ld", frames);
3444		return -EINVAL;
3445	}
3446	while (channels > 0) {
3447		unsigned int step = src_areas->step;
3448		void *src_addr = src_areas->addr;
3449		const snd_pcm_channel_area_t *src_start = src_areas;
3450		void *dst_addr = dst_areas->addr;
3451		const snd_pcm_channel_area_t *dst_start = dst_areas;
3452		int channels1 = channels;
3453		unsigned int chns = 0;
3454		while (dst_areas->step == step) {
3455			channels1--;
3456			chns++;
3457			src_areas++;
3458			dst_areas++;
3459			if (channels1 == 0 ||
3460			    src_areas->step != step ||
3461			    src_areas->addr != src_addr ||
3462			    dst_areas->addr != dst_addr ||
3463			    src_areas->first != src_areas[-1].first + width ||
3464			    dst_areas->first != dst_areas[-1].first + width)
3465				break;
3466		}
3467		if (chns > 1 && chns * width == step) {
3468			if (src_offset != dst_offset ||
3469			    src_start->addr != dst_start->addr ||
3470			    src_start->first != dst_start->first) {
3471				/* Collapse the areas */
3472				snd_pcm_channel_area_t s, d;
3473				s.addr = src_start->addr;
3474				s.first = src_start->first;
3475				s.step = width;
3476				d.addr = dst_start->addr;
3477				d.first = dst_start->first;
3478				d.step = width;
3479				snd_pcm_area_copy(&d, dst_offset * chns,
3480						  &s, src_offset * chns,
3481						  frames * chns, format);
3482			}
3483			channels -= chns;
3484		} else {
3485			snd_pcm_area_copy(dst_start, dst_offset,
3486					  src_start, src_offset,
3487					  frames, format);
3488			src_areas = src_start + 1;
3489			dst_areas = dst_start + 1;
3490			channels--;
3491		}
3492	}
3493	return 0;
3494}
3495
3496/**
3497 * \brief Copy one or more areas
3498 * \param dst_channels destination areas specification (one for each channel)
3499 * \param dst_offset offset in frames inside destination area
3500 * \param dst_size size in frames of the destination buffer
3501 * \param src_channels source areas specification (one for each channel)
3502 * \param src_offset offset in frames inside source area
3503 * \param src_size size in frames of the source buffer
3504 * \param channels channels count
3505 * \param frames frames to copy
3506 * \param format PCM sample format
3507 * \return 0 on success otherwise a negative error code
3508 */
3509int snd_pcm_areas_copy_wrap(const snd_pcm_channel_area_t *dst_channels,
3510			    snd_pcm_uframes_t dst_offset,
3511			    const snd_pcm_uframes_t dst_size,
3512			    const snd_pcm_channel_area_t *src_channels,
3513			    snd_pcm_uframes_t src_offset,
3514			    const snd_pcm_uframes_t src_size,
3515			    const unsigned int channels,
3516			    snd_pcm_uframes_t frames,
3517			    const snd_pcm_format_t format)
3518{
3519	while (frames > 0) {
3520		int err;
3521		snd_pcm_uframes_t xfer = frames;
3522		/* do not write above the destination buffer */
3523		if ((dst_offset + xfer) > dst_size)
3524			xfer = dst_size - dst_offset;
3525		/* do not read from above the source buffer */
3526		if ((src_offset + xfer) > src_size)
3527			xfer = src_size - src_offset;
3528		err = snd_pcm_areas_copy(dst_channels, dst_offset, src_channels,
3529					 src_offset, channels, xfer, format);
3530		if (err < 0)
3531			return err;
3532
3533		dst_offset += xfer;
3534		if (dst_offset >= dst_size)
3535			dst_offset = 0;
3536		src_offset += xfer;
3537		if (src_offset >= src_size)
3538			src_offset = 0;
3539		frames -= xfer;
3540	}
3541
3542	return 0;
3543}
3544
3545static void dump_one_param(snd_pcm_hw_params_t *params, unsigned int k, snd_output_t *out)
3546{
3547	snd_output_printf(out, "%s: ", snd_pcm_hw_param_name(k));
3548	snd_pcm_hw_param_dump(params, k, out);
3549	snd_output_putc(out, '\n');
3550}
3551
3552/**
3553 * \brief Dump a PCM hardware configuration space
3554 * \param params Configuration space
3555 * \param out Output handle
3556 * \return 0 on success otherwise a negative error code
3557 */
3558int snd_pcm_hw_params_dump(snd_pcm_hw_params_t *params, snd_output_t *out)
3559{
3560	unsigned int k;
3561	for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++)
3562		dump_one_param(params, k, out);
3563	for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++)
3564		dump_one_param(params, k, out);
3565	return 0;
3566}
3567
3568/**
3569 * \brief Check if hardware supports sample-resolution mmap for given configuration
3570 * \param params Configuration space
3571 * \retval 0 Hardware doesn't support sample-resolution mmap
3572 * \retval 1 Hardware supports sample-resolution mmap
3573 *
3574 * This function should only be called when the configuration space
3575 * contains a single configuration. Call #snd_pcm_hw_params to choose
3576 * a single configuration from the configuration space.
3577 */
3578int snd_pcm_hw_params_can_mmap_sample_resolution(const snd_pcm_hw_params_t *params)
3579{
3580	assert(params);
3581	if (CHECK_SANITY(params->info == ~0U)) {
3582		SNDMSG("invalid PCM info field");
3583		return 0; /* FIXME: should be a negative error? */
3584	}
3585	return !!(params->info & SNDRV_PCM_INFO_MMAP_VALID);
3586}
3587
3588/**
3589 * \brief Check if hardware does double buffering for start/stop for given configuration
3590 * \param params Configuration space
3591 * \retval 0 Hardware doesn't do double buffering for start/stop
3592 * \retval 1 Hardware does double buffering for start/stop
3593 *
3594 * This function should only be called when the configuration space
3595 * contains a single configuration. Call #snd_pcm_hw_params to choose
3596 * a single configuration from the configuration space.
3597 */
3598int snd_pcm_hw_params_is_double(const snd_pcm_hw_params_t *params)
3599{
3600	assert(params);
3601	if (CHECK_SANITY(params->info == ~0U)) {
3602		SNDMSG("invalid PCM info field");
3603		return 0; /* FIXME: should be a negative error? */
3604	}
3605	return !!(params->info & SNDRV_PCM_INFO_DOUBLE);
3606}
3607
3608/**
3609 * \brief Check if hardware does double buffering for data transfers for given configuration
3610 * \param params Configuration space
3611 * \retval 0 Hardware doesn't do double buffering for data transfers
3612 * \retval 1 Hardware does double buffering for data transfers
3613 *
3614 * This function should only be called when the configuration space
3615 * contains a single configuration. Call #snd_pcm_hw_params to choose
3616 * a single configuration from the configuration space.
3617 */
3618int snd_pcm_hw_params_is_batch(const snd_pcm_hw_params_t *params)
3619{
3620	assert(params);
3621	if (CHECK_SANITY(params->info == ~0U)) {
3622		SNDMSG("invalid PCM info field");
3623		return 0; /* FIXME: should be a negative error? */
3624	}
3625	return !!(params->info & SNDRV_PCM_INFO_BATCH);
3626}
3627
3628/**
3629 * \brief Check if hardware does block transfers for samples for given configuration
3630 * \param params Configuration space
3631 * \retval 0 Hardware doesn't block transfers
3632 * \retval 1 Hardware does block transfers
3633 *
3634 * This function should only be called when the configuration space
3635 * contains a single configuration. Call #snd_pcm_hw_params to choose
3636 * a single configuration from the configuration space.
3637 */
3638int snd_pcm_hw_params_is_block_transfer(const snd_pcm_hw_params_t *params)
3639{
3640	assert(params);
3641	if (CHECK_SANITY(params->info == ~0U)) {
3642		SNDMSG("invalid PCM info field");
3643		return 0; /* FIXME: should be a negative error? */
3644	}
3645	return !!(params->info & SNDRV_PCM_INFO_BLOCK_TRANSFER);
3646}
3647
3648/**
3649 * \brief Check if timestamps are monotonic for given configuration
3650 * \param params Configuration space
3651 * \retval 0 Device doesn't do monotomic timestamps
3652 * \retval 1 Device does monotonic timestamps
3653 *
3654 * This function should only be called when the configuration space
3655 * contains a single configuration. Call #snd_pcm_hw_params to choose
3656 * a single configuration from the configuration space.
3657 */
3658int snd_pcm_hw_params_is_monotonic(const snd_pcm_hw_params_t *params)
3659{
3660	assert(params);
3661	if (CHECK_SANITY(params->info == ~0U)) {
3662		SNDMSG("invalid PCM info field");
3663		return 0; /* FIXME: should be a negative error? */
3664	}
3665	return !!(params->info & SND_PCM_INFO_MONOTONIC);
3666}
3667
3668/**
3669 * \brief Check if hardware supports overrange detection
3670 * \param params Configuration space
3671 * \retval 0 Hardware doesn't support overrange detection
3672 * \retval 1 Hardware supports overrange detection
3673 *
3674 * This function should only be called when the configuration space
3675 * contains a single configuration. Call #snd_pcm_hw_params to choose
3676 * a single configuration from the configuration space.
3677 */
3678int snd_pcm_hw_params_can_overrange(const snd_pcm_hw_params_t *params)
3679{
3680	assert(params);
3681	if (CHECK_SANITY(params->info == ~0U)) {
3682		SNDMSG("invalid PCM info field");
3683		return 0; /* FIXME: should be a negative error? */
3684	}
3685	return !!(params->info & SNDRV_PCM_INFO_OVERRANGE);
3686}
3687
3688/**
3689 * \brief Check if hardware supports pause
3690 * \param params Configuration space
3691 * \retval 0 Hardware doesn't support pause
3692 * \retval 1 Hardware supports pause
3693 *
3694 * This function should only be called when the configuration space
3695 * contains a single configuration. Call #snd_pcm_hw_params to choose
3696 * a single configuration from the configuration space.
3697 */
3698int snd_pcm_hw_params_can_pause(const snd_pcm_hw_params_t *params)
3699{
3700	assert(params);
3701	if (CHECK_SANITY(params->info == ~0U)) {
3702		SNDMSG("invalid PCM info field");
3703		return 0; /* FIXME: should be a negative error? */
3704	}
3705	return !!(params->info & SNDRV_PCM_INFO_PAUSE);
3706}
3707
3708/**
3709 * \brief Check if hardware supports resume
3710 * \param params Configuration space
3711 * \retval 0 Hardware doesn't support resume
3712 * \retval 1 Hardware supports resume
3713 *
3714 * This function should only be called when the configuration space
3715 * contains a single configuration. Call #snd_pcm_hw_params to choose
3716 * a single configuration from the configuration space.
3717 */
3718int snd_pcm_hw_params_can_resume(const snd_pcm_hw_params_t *params)
3719{
3720	assert(params);
3721	if (CHECK_SANITY(params->info == ~0U)) {
3722		SNDMSG("invalid PCM info field");
3723		return 0; /* FIXME: should be a negative error? */
3724	}
3725	return !!(params->info & SNDRV_PCM_INFO_RESUME);
3726}
3727
3728/**
3729 * \brief Check if hardware does half-duplex only
3730 * \param params Configuration space
3731 * \retval 0 Hardware doesn't do half-duplex
3732 * \retval 1 Hardware does half-duplex
3733 *
3734 * This function should only be called when the configuration space
3735 * contains a single configuration. Call #snd_pcm_hw_params to choose
3736 * a single configuration from the configuration space.
3737 */
3738int snd_pcm_hw_params_is_half_duplex(const snd_pcm_hw_params_t *params)
3739{
3740	assert(params);
3741	if (CHECK_SANITY(params->info == ~0U)) {
3742		SNDMSG("invalid PCM info field");
3743		return 0; /* FIXME: should be a negative error? */
3744	}
3745	return !!(params->info & SNDRV_PCM_INFO_HALF_DUPLEX);
3746}
3747
3748/**
3749 * \brief Check if hardware does joint-duplex (playback and capture are somewhat correlated)
3750 * \param params Configuration space
3751 * \retval 0 Hardware doesn't do joint-duplex
3752 * \retval 1 Hardware does joint-duplex
3753 *
3754 * This function should only be called when the configuration space
3755 * contains a single configuration. Call #snd_pcm_hw_params to choose
3756 * a single configuration from the configuration space.
3757 */
3758int snd_pcm_hw_params_is_joint_duplex(const snd_pcm_hw_params_t *params)
3759{
3760	assert(params);
3761	if (CHECK_SANITY(params->info == ~0U)) {
3762		SNDMSG("invalid PCM info field");
3763		return 0; /* FIXME: should be a negative error? */
3764	}
3765	return !!(params->info & SNDRV_PCM_INFO_JOINT_DUPLEX);
3766}
3767
3768/**
3769 * \brief Check if hardware supports synchronized start with sample resolution
3770 * \param params Configuration space
3771 * \retval 0 Hardware doesn't support synchronized start
3772 * \retval 1 Hardware supports synchronized start
3773 *
3774 * This function should only be called when the configuration space
3775 * contains a single configuration. Call #snd_pcm_hw_params to choose
3776 * a single configuration from the configuration space.
3777 */
3778int snd_pcm_hw_params_can_sync_start(const snd_pcm_hw_params_t *params)
3779{
3780	assert(params);
3781	if (CHECK_SANITY(params->info == ~0U)) {
3782		SNDMSG("invalid PCM info field");
3783		return 0; /* FIXME: should be a negative error? */
3784	}
3785	return !!(params->info & SNDRV_PCM_INFO_SYNC_START);
3786}
3787
3788/**
3789 * \brief Check if hardware can disable period wakeups
3790 * \param params Configuration space
3791 * \retval 0 Hardware cannot disable period wakeups
3792 * \retval 1 Hardware can disable period wakeups
3793 */
3794int snd_pcm_hw_params_can_disable_period_wakeup(const snd_pcm_hw_params_t *params)
3795{
3796	assert(params);
3797	if (CHECK_SANITY(params->info == ~0U)) {
3798		SNDMSG("invalid PCM info field");
3799		return 0; /* FIXME: should be a negative error? */
3800	}
3801	return !!(params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP);
3802}
3803
3804/**
3805 * \brief Check if hardware is capable of perfect drain
3806 * \param params Configuration space
3807 * \retval 0 Hardware doesn't do perfect drain
3808 * \retval 1 Hardware does perfect drain
3809 *
3810 * This function should only be called when the configuration space
3811 * contains a single configuration. Call #snd_pcm_hw_params to choose
3812 * a single configuration from the configuration space.
3813 *
3814 * Perfect drain means that the hardware does not use samples
3815 * beyond the stream application pointer.
3816 */
3817int snd_pcm_hw_params_is_perfect_drain(const snd_pcm_hw_params_t *params)
3818{
3819	assert(params);
3820	if (CHECK_SANITY(params->info == ~0U)) {
3821		SNDMSG("invalid PCM info field");
3822		return 0; /* FIXME: should be a negative error? */
3823	}
3824	return !!(params->info & SNDRV_PCM_INFO_PERFECT_DRAIN);
3825}
3826
3827/**
3828 * \brief Check if hardware supports audio wallclock timestamps
3829 * \param params Configuration space
3830 * \retval 0 Hardware doesn't support audio wallclock timestamps
3831 * \retval 1 Hardware supports audio wallclock timestamps
3832 *
3833 * This function should only be called when the configuration space
3834 * contains a single configuration. Call #snd_pcm_hw_params to choose
3835 * a single configuration from the configuration space.
3836 */
3837int snd_pcm_hw_params_supports_audio_wallclock_ts(const snd_pcm_hw_params_t *params)
3838{
3839	/* deprecated */
3840	return snd_pcm_hw_params_supports_audio_ts_type(params,
3841							SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT);
3842}
3843
3844/**
3845 * \brief Check if hardware supports type of audio timestamps
3846 * \param params Configuration space
3847 * \param type   Audio timestamp type
3848 * \retval 0 Hardware doesn't support type of audio timestamps
3849 * \retval 1 Hardware supports type of audio timestamps
3850 *
3851 * This function should only be called when the configuration space
3852 * contains a single configuration. Call #snd_pcm_hw_params to choose
3853 * a single configuration from the configuration space.
3854 */
3855int snd_pcm_hw_params_supports_audio_ts_type(const snd_pcm_hw_params_t *params, int type)
3856{
3857	assert(params);
3858	if (CHECK_SANITY(params->info == ~0U)) {
3859		SNDMSG("invalid PCM info field");
3860		return 0; /* FIXME: should be a negative error? */
3861	}
3862	switch (type) {
3863	case SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT:
3864		return !!(params->info & SNDRV_PCM_INFO_HAS_WALL_CLOCK); /* deprecated */
3865	case SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT:
3866		return 1; /* always supported, based on hw_ptr */
3867	case SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK:
3868		return !!(params->info & SNDRV_PCM_INFO_HAS_LINK_ATIME);
3869	case SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE:
3870		return !!(params->info & SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME);
3871	case SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED:
3872		return !!(params->info & SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME);
3873	case SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED:
3874		return !!(params->info & SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME);
3875	default:
3876		return 0;
3877	}
3878}
3879
3880/**
3881 * \brief Get rate exact info from a configuration space
3882 * \param params Configuration space
3883 * \param rate_num Pointer to returned rate numerator
3884 * \param rate_den Pointer to returned rate denominator
3885 * \return 0 otherwise a negative error code if the info is not available
3886 *
3887 * This function should only be called when the configuration space
3888 * contains a single configuration. Call #snd_pcm_hw_params to choose
3889 * a single configuration from the configuration space.
3890 */
3891int snd_pcm_hw_params_get_rate_numden(const snd_pcm_hw_params_t *params,
3892				      unsigned int *rate_num, unsigned int *rate_den)
3893{
3894	assert(params);
3895	if (CHECK_SANITY(params->rate_den == 0)) {
3896		SNDMSG("invalid rate_den value");
3897		return -EINVAL;
3898	}
3899	*rate_num = params->rate_num;
3900	*rate_den = params->rate_den;
3901	return 0;
3902}
3903
3904/**
3905 * \brief Get sample resolution info from a configuration space
3906 * \param params Configuration space
3907 * \return sample resolution (in bits) otherwise a negative error code if the info is not available
3908 *
3909 * For linear formats, this function returns sample resolution -
3910 * used bits starting from the first usable significant bit defined by
3911 * the format (e.g. bit 31 for S32_LE format or bit 23 for S24_LE format -
3912 * starting from bit zero). Application may use full sample bit range defined
3913 * by the format, but additional bits (outside this sample resolution) are
3914 * stripped (not processed).
3915 *
3916 * For non-linear formats, this value may have a special meaning which may be defined in future.
3917 *
3918 * This function should only be called when the configuration space
3919 * contains a single configuration. Call #snd_pcm_hw_params to choose
3920 * a single configuration from the configuration space.
3921 */
3922int snd_pcm_hw_params_get_sbits(const snd_pcm_hw_params_t *params)
3923{
3924	assert(params);
3925	if (CHECK_SANITY(params->msbits == 0)) {
3926		SNDMSG("invalid msbits value");
3927		return -EINVAL;
3928	}
3929	return params->msbits;
3930}
3931
3932/**
3933 * \brief Get hardware FIFO size info from a configuration space
3934 * \param params Configuration space
3935 * \return FIFO size in frames otherwise a negative error code if the info is not available
3936 *
3937 * This function should only be called when the configuration space
3938 * contains a single configuration. Call #snd_pcm_hw_params to choose
3939 * a single configuration from the configuration space.
3940 */
3941int snd_pcm_hw_params_get_fifo_size(const snd_pcm_hw_params_t *params)
3942{
3943	assert(params);
3944	if (CHECK_SANITY(params->info == ~0U)) {
3945		SNDMSG("invalid PCM info field");
3946		return -EINVAL;
3947	}
3948	return params->fifo_size;
3949}
3950
3951/**
3952 * \brief Fill params with a full configuration space for a PCM
3953 * \param pcm PCM handle
3954 * \param params Configuration space
3955 *
3956 * The configuration space will be filled with all possible ranges
3957 * for the PCM device.
3958 *
3959 * Note that the configuration space may be constrained by the
3960 * currently installed configuration on the PCM device. To remove
3961 * any constrains, free the configuration with #snd_pcm_hw_free
3962 * first.
3963 */
3964int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
3965{
3966	_snd_pcm_hw_params_any(params);
3967	return snd_pcm_hw_refine(pcm, params);
3968}
3969
3970/**
3971 * \brief get size of #snd_pcm_access_mask_t
3972 * \return size in bytes
3973 */
3974size_t snd_pcm_access_mask_sizeof()
3975{
3976	return sizeof(snd_pcm_access_mask_t);
3977}
3978
3979/**
3980 * \brief allocate an empty #snd_pcm_access_mask_t using standard malloc
3981 * \param ptr returned pointer
3982 * \return 0 on success otherwise negative error code
3983 */
3984int snd_pcm_access_mask_malloc(snd_pcm_access_mask_t **ptr)
3985{
3986	assert(ptr);
3987	*ptr = calloc(1, sizeof(snd_pcm_access_mask_t));
3988	if (!*ptr)
3989		return -ENOMEM;
3990	return 0;
3991}
3992
3993/**
3994 * \brief frees a previously allocated #snd_pcm_access_mask_t
3995 * \param obj pointer to object to free
3996 */
3997void snd_pcm_access_mask_free(snd_pcm_access_mask_t *obj)
3998{
3999	free(obj);
4000}
4001
4002/**
4003 * \brief copy one #snd_pcm_access_mask_t to another
4004 * \param dst pointer to destination
4005 * \param src pointer to source
4006 */
4007void snd_pcm_access_mask_copy(snd_pcm_access_mask_t *dst, const snd_pcm_access_mask_t *src)
4008{
4009	assert(dst && src);
4010	*dst = *src;
4011}
4012
4013/**
4014 * \brief reset all bits in a #snd_pcm_access_mask_t
4015 * \param mask pointer to mask
4016 */
4017void snd_pcm_access_mask_none(snd_pcm_access_mask_t *mask)
4018{
4019	snd_mask_none((snd_mask_t *) mask);
4020}
4021
4022/**
4023 * \brief set all bits in a #snd_pcm_access_mask_t
4024 * \param mask pointer to mask
4025 */
4026void snd_pcm_access_mask_any(snd_pcm_access_mask_t *mask)
4027{
4028	snd_mask_any((snd_mask_t *) mask);
4029}
4030
4031/**
4032 * \brief test the presence of an access type in a #snd_pcm_access_mask_t
4033 * \param mask pointer to mask
4034 * \param val access type
4035 */
4036int snd_pcm_access_mask_test(const snd_pcm_access_mask_t *mask, snd_pcm_access_t val)
4037{
4038	return snd_mask_test((const snd_mask_t *) mask, (unsigned long) val);
4039}
4040
4041/**
4042 * \brief test, if given a #snd_pcm_access_mask_t is empty
4043 * \param mask pointer to mask
4044 * \retval 0 not empty
4045 * \retval 1 empty
4046 */
4047int snd_pcm_access_mask_empty(const snd_pcm_access_mask_t *mask)
4048{
4049	return snd_mask_empty((const snd_mask_t *) mask);
4050}
4051
4052/**
4053 * \brief make an access type present in a #snd_pcm_access_mask_t
4054 * \param mask pointer to mask
4055 * \param val access type
4056 */
4057void snd_pcm_access_mask_set(snd_pcm_access_mask_t *mask, snd_pcm_access_t val)
4058{
4059	snd_mask_set((snd_mask_t *) mask, (unsigned long) val);
4060}
4061
4062/**
4063 * \brief make an access type missing from a #snd_pcm_access_mask_t
4064 * \param mask pointer to mask
4065 * \param val access type
4066 */
4067void snd_pcm_access_mask_reset(snd_pcm_access_mask_t *mask, snd_pcm_access_t val)
4068{
4069	snd_mask_reset((snd_mask_t *) mask, (unsigned long) val);
4070}
4071
4072/**
4073 * \brief get size of #snd_pcm_format_mask_t
4074 * \return size in bytes
4075 */
4076size_t snd_pcm_format_mask_sizeof()
4077{
4078	return sizeof(snd_pcm_format_mask_t);
4079}
4080
4081/**
4082 * \brief allocate an empty #snd_pcm_format_mask_t using standard malloc
4083 * \param ptr returned pointer
4084 * \return 0 on success otherwise negative error code
4085 */
4086int snd_pcm_format_mask_malloc(snd_pcm_format_mask_t **ptr)
4087{
4088	assert(ptr);
4089	*ptr = calloc(1, sizeof(snd_pcm_format_mask_t));
4090	if (!*ptr)
4091		return -ENOMEM;
4092	return 0;
4093}
4094
4095/**
4096 * \brief frees a previously allocated #snd_pcm_format_mask_t
4097 * \param obj pointer to object to free
4098 */
4099void snd_pcm_format_mask_free(snd_pcm_format_mask_t *obj)
4100{
4101	free(obj);
4102}
4103
4104/**
4105 * \brief copy one #snd_pcm_format_mask_t to another
4106 * \param dst pointer to destination
4107 * \param src pointer to source
4108 */
4109void snd_pcm_format_mask_copy(snd_pcm_format_mask_t *dst, const snd_pcm_format_mask_t *src)
4110{
4111	assert(dst && src);
4112	*dst = *src;
4113}
4114
4115/**
4116 * \brief reset all bits in a #snd_pcm_format_mask_t
4117 * \param mask pointer to mask
4118 */
4119void snd_pcm_format_mask_none(snd_pcm_format_mask_t *mask)
4120{
4121	snd_mask_none((snd_mask_t *) mask);
4122}
4123
4124/**
4125 * \brief set all bits in a #snd_pcm_format_mask_t
4126 * \param mask pointer to mask
4127 */
4128void snd_pcm_format_mask_any(snd_pcm_format_mask_t *mask)
4129{
4130	snd_mask_any((snd_mask_t *) mask);
4131}
4132
4133/**
4134 * \brief test the presence of a format in a #snd_pcm_format_mask_t
4135 * \param mask pointer to mask
4136 * \param val format
4137 */
4138int snd_pcm_format_mask_test(const snd_pcm_format_mask_t *mask, snd_pcm_format_t val)
4139{
4140	return snd_mask_test((const snd_mask_t *) mask, (unsigned long) val);
4141}
4142
4143/**
4144 * \brief test, if given a #snd_pcm_format_mask_t is empty
4145 * \param mask pointer to mask
4146 * \retval 0 not empty
4147 * \retval 1 empty
4148 */
4149int snd_pcm_format_mask_empty(const snd_pcm_format_mask_t *mask)
4150{
4151	return snd_mask_empty((const snd_mask_t *) mask);
4152}
4153
4154/**
4155 * \brief make a format present in a #snd_pcm_format_mask_t
4156 * \param mask pointer to mask
4157 * \param val format
4158 */
4159void snd_pcm_format_mask_set(snd_pcm_format_mask_t *mask, snd_pcm_format_t val)
4160{
4161	snd_mask_set((snd_mask_t *) mask, (unsigned long) val);
4162}
4163
4164/**
4165 * \brief make a format missing from a #snd_pcm_format_mask_t
4166 * \param mask pointer to mask
4167 * \param val format
4168 */
4169void snd_pcm_format_mask_reset(snd_pcm_format_mask_t *mask, snd_pcm_format_t val)
4170{
4171	snd_mask_reset((snd_mask_t *) mask, (unsigned long) val);
4172}
4173
4174
4175/**
4176 * \brief get size of #snd_pcm_subformat_mask_t
4177 * \return size in bytes
4178 */
4179size_t snd_pcm_subformat_mask_sizeof()
4180{
4181	return sizeof(snd_pcm_subformat_mask_t);
4182}
4183
4184/**
4185 * \brief allocate an empty #snd_pcm_subformat_mask_t using standard malloc
4186 * \param ptr returned pointer
4187 * \return 0 on success otherwise negative error code
4188 */
4189int snd_pcm_subformat_mask_malloc(snd_pcm_subformat_mask_t **ptr)
4190{
4191	assert(ptr);
4192	*ptr = calloc(1, sizeof(snd_pcm_subformat_mask_t));
4193	if (!*ptr)
4194		return -ENOMEM;
4195	return 0;
4196}
4197
4198/**
4199 * \brief frees a previously allocated #snd_pcm_subformat_mask_t
4200 * \param obj pointer to object to free
4201 */
4202void snd_pcm_subformat_mask_free(snd_pcm_subformat_mask_t *obj)
4203{
4204	free(obj);
4205}
4206
4207/**
4208 * \brief copy one #snd_pcm_subformat_mask_t to another
4209 * \param dst pointer to destination
4210 * \param src pointer to source
4211 */
4212void snd_pcm_subformat_mask_copy(snd_pcm_subformat_mask_t *dst, const snd_pcm_subformat_mask_t *src)
4213{
4214	assert(dst && src);
4215	*dst = *src;
4216}
4217
4218/**
4219 * \brief reset all bits in a #snd_pcm_subformat_mask_t
4220 * \param mask pointer to mask
4221 */
4222void snd_pcm_subformat_mask_none(snd_pcm_subformat_mask_t *mask)
4223{
4224	snd_mask_none((snd_mask_t *) mask);
4225}
4226
4227/**
4228 * \brief set all bits in a #snd_pcm_subformat_mask_t
4229 * \param mask pointer to mask
4230 */
4231void snd_pcm_subformat_mask_any(snd_pcm_subformat_mask_t *mask)
4232{
4233	snd_mask_any((snd_mask_t *) mask);
4234}
4235
4236/**
4237 * \brief test the presence of a subformat in a #snd_pcm_subformat_mask_t
4238 * \param mask pointer to mask
4239 * \param val subformat
4240 */
4241int snd_pcm_subformat_mask_test(const snd_pcm_subformat_mask_t *mask, snd_pcm_subformat_t val)
4242{
4243	return snd_mask_test((const snd_mask_t *) mask, (unsigned long) val);
4244}
4245
4246/**
4247 * \brief test, if given a #snd_pcm_subformat_mask_t is empty
4248 * \param mask pointer to mask
4249 * \retval 0 not empty
4250 * \retval 1 empty
4251 */
4252int snd_pcm_subformat_mask_empty(const snd_pcm_subformat_mask_t *mask)
4253{
4254	return snd_mask_empty((const snd_mask_t *) mask);
4255}
4256
4257/**
4258 * \brief make a subformat present in a #snd_pcm_subformat_mask_t
4259 * \param mask pointer to mask
4260 * \param val subformat
4261 */
4262void snd_pcm_subformat_mask_set(snd_pcm_subformat_mask_t *mask, snd_pcm_subformat_t val)
4263{
4264	snd_mask_set((snd_mask_t *) mask, (unsigned long) val);
4265}
4266
4267/**
4268 * \brief make a subformat missing from a #snd_pcm_subformat_mask_t
4269 * \param mask pointer to mask
4270 * \param val subformat
4271 */
4272void snd_pcm_subformat_mask_reset(snd_pcm_subformat_mask_t *mask, snd_pcm_subformat_t val)
4273{
4274	snd_mask_reset((snd_mask_t *) mask, (unsigned long) val);
4275}
4276
4277
4278/**
4279 * \brief get size of #snd_pcm_hw_params_t
4280 * \return size in bytes
4281 */
4282size_t snd_pcm_hw_params_sizeof()
4283{
4284	return sizeof(snd_pcm_hw_params_t);
4285}
4286
4287/**
4288 * \brief allocate an invalid #snd_pcm_hw_params_t using standard malloc
4289 * \param ptr returned pointer
4290 * \return 0 on success otherwise negative error code
4291 */
4292int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t **ptr)
4293{
4294	assert(ptr);
4295	*ptr = calloc(1, sizeof(snd_pcm_hw_params_t));
4296	if (!*ptr)
4297		return -ENOMEM;
4298	return 0;
4299}
4300
4301/**
4302 * \brief frees a previously allocated #snd_pcm_hw_params_t
4303 * \param obj pointer to object to free
4304 */
4305void snd_pcm_hw_params_free(snd_pcm_hw_params_t *obj)
4306{
4307	free(obj);
4308}
4309
4310/**
4311 * \brief copy one #snd_pcm_hw_params_t to another
4312 * \param dst pointer to destination
4313 * \param src pointer to source
4314 */
4315void snd_pcm_hw_params_copy(snd_pcm_hw_params_t *dst, const snd_pcm_hw_params_t *src)
4316{
4317	assert(dst && src);
4318	*dst = *src;
4319}
4320
4321
4322/**
4323 * \brief Extract access type from a configuration space
4324 * \param params Configuration space
4325 * \param access Returned value
4326 * \return access type otherwise a negative error code if the configuration space does not contain a single value
4327 */
4328#ifndef DOXYGEN
4329EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_access)(const snd_pcm_hw_params_t *params, snd_pcm_access_t *access)
4330#else
4331int snd_pcm_hw_params_get_access(const snd_pcm_hw_params_t *params, snd_pcm_access_t *access)
4332#endif
4333{
4334	unsigned int _val;
4335	int err = snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_ACCESS, &_val, NULL);
4336	if (err >= 0)
4337		*access = _val;
4338	return err;
4339}
4340
4341/**
4342 * \brief Verify if an access type is available inside a configuration space for a PCM
4343 * \param pcm PCM handle
4344 * \param params Configuration space
4345 * \param access access type
4346 * \return 0 if available a negative error code otherwise
4347 */
4348int snd_pcm_hw_params_test_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access)
4349{
4350	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_ACCESS, access, 0);
4351}
4352
4353/**
4354 * \brief Restrict a configuration space to contain only one access type
4355 * \param pcm PCM handle
4356 * \param params Configuration space
4357 * \param access access type
4358 * \return 0 otherwise a negative error code if configuration space would become empty
4359 */
4360int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access)
4361{
4362	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_ACCESS, access, 0);
4363}
4364
4365/**
4366 * \brief Restrict a configuration space to contain only its first access type
4367 * \param pcm PCM handle
4368 * \param params Configuration space
4369 * \param access Returned first access type
4370 * \return 0 otherwise a negative error code
4371 */
4372#ifndef DOXYGEN
4373EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_access_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t *access)
4374#else
4375int snd_pcm_hw_params_set_access_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t *access)
4376#endif
4377{
4378	return snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, access, NULL);
4379}
4380
4381/**
4382 * \brief Restrict a configuration space to contain only its last access type
4383 * \param pcm PCM handle
4384 * \param params Configuration space
4385 * \param access Returned last access type
4386 * \return 0 otherwise a negative error code
4387 */
4388#ifndef DOXYGEN
4389EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_access_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t *access)
4390#else
4391int snd_pcm_hw_params_set_access_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t *access)
4392#endif
4393{
4394	return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_ACCESS, access, NULL);
4395}
4396
4397/**
4398 * \brief Restrict a configuration space to contain only a set of access types
4399 * \param pcm PCM handle
4400 * \param params Configuration space
4401 * \param mask Access mask
4402 * \return 0 otherwise a negative error code
4403 */
4404int snd_pcm_hw_params_set_access_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask)
4405{
4406	return snd_pcm_hw_param_set_mask(pcm, params, SND_TRY, SND_PCM_HW_PARAM_ACCESS, (snd_mask_t *) mask);
4407}
4408
4409/**
4410 * \brief Get access mask from a configuration space
4411 * \param params Configuration space
4412 * \param mask Returned Access mask
4413 */
4414int snd_pcm_hw_params_get_access_mask(snd_pcm_hw_params_t *params, snd_pcm_access_mask_t *mask)
4415{
4416	if (params == NULL || mask == NULL)
4417		return -EINVAL;
4418	snd_pcm_access_mask_copy(mask, snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS));
4419	return 0;
4420}
4421
4422
4423/**
4424 * \brief Extract format from a configuration space
4425 * \param params Configuration space
4426 * \param format returned format
4427 * \return format otherwise a negative error code if the configuration space does not contain a single value
4428 */
4429#ifndef DOXYGEN
4430EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_format)(const snd_pcm_hw_params_t *params, snd_pcm_format_t *format)
4431#else
4432int snd_pcm_hw_params_get_format(const snd_pcm_hw_params_t *params, snd_pcm_format_t *format)
4433#endif
4434{
4435	return snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_FORMAT, (unsigned int *)format, NULL);
4436}
4437
4438/**
4439 * \brief Verify if a format is available inside a configuration space for a PCM
4440 * \param pcm PCM handle
4441 * \param params Configuration space
4442 * \param format format
4443 * \return 0 if available a negative error code otherwise
4444 */
4445int snd_pcm_hw_params_test_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t format)
4446{
4447	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_FORMAT, format, 0);
4448}
4449
4450/**
4451 * \brief Restrict a configuration space to contain only one format
4452 * \param pcm PCM handle
4453 * \param params Configuration space
4454 * \param format format
4455 * \return 0 otherwise a negative error code
4456 */
4457int snd_pcm_hw_params_set_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t format)
4458{
4459	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_FORMAT, format, 0);
4460}
4461
4462/**
4463 * \brief Restrict a configuration space to contain only its first format
4464 * \param pcm PCM handle
4465 * \param params Configuration space
4466 * \param format Returned first format
4467 * \return 0 otherwise a negative error code
4468 */
4469#ifndef DOXYGEN
4470EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_format_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t *format)
4471#else
4472int snd_pcm_hw_params_set_format_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t *format)
4473#endif
4474{
4475	return snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_FORMAT, (unsigned int *)format, NULL);
4476}
4477
4478/**
4479 * \brief Restrict a configuration space to contain only its last format
4480 * \param pcm PCM handle
4481 * \param params Configuration space
4482 * \param format Returned last format
4483 * \return 0 otherwise a negative error code
4484 */
4485#ifndef DOXYGEN
4486EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_format_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t *format)
4487#else
4488int snd_pcm_hw_params_set_format_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t *format)
4489#endif
4490{
4491	return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_FORMAT, (unsigned int *)format, NULL);
4492}
4493
4494/**
4495 * \brief Restrict a configuration space to contain only a set of formats
4496 * \param pcm PCM handle
4497 * \param params Configuration space
4498 * \param mask Format mask
4499 * \return 0 otherwise a negative error code
4500 */
4501int snd_pcm_hw_params_set_format_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask)
4502{
4503	return snd_pcm_hw_param_set_mask(pcm, params, SND_TRY, SND_PCM_HW_PARAM_FORMAT, (snd_mask_t *) mask);
4504}
4505
4506/**
4507 * \brief Get format mask from a configuration space
4508 * \param params Configuration space
4509 * \param mask Returned Format mask
4510 */
4511void snd_pcm_hw_params_get_format_mask(snd_pcm_hw_params_t *params, snd_pcm_format_mask_t *mask)
4512{
4513	snd_pcm_format_mask_copy(mask, snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_FORMAT));
4514}
4515
4516
4517/**
4518 * \brief Extract subformat from a configuration space
4519 * \param params Configuration space
4520 * \param subformat Returned subformat value
4521 * \return subformat otherwise a negative error code if the configuration space does not contain a single value
4522 */
4523#ifndef DOXYGEN
4524EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_subformat)(const snd_pcm_hw_params_t *params, snd_pcm_subformat_t *subformat)
4525#else
4526int snd_pcm_hw_params_get_subformat(const snd_pcm_hw_params_t *params, snd_pcm_subformat_t *subformat)
4527#endif
4528{
4529	return snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_SUBFORMAT, (unsigned int *)subformat, NULL);
4530}
4531
4532/**
4533 * \brief Verify if a subformat is available inside a configuration space for a PCM
4534 * \param pcm PCM handle
4535 * \param params Configuration space
4536 * \param subformat subformat value
4537 * \return 0 if available a negative error code otherwise
4538 */
4539int snd_pcm_hw_params_test_subformat(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t subformat)
4540{
4541	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_SUBFORMAT, subformat, 0);
4542}
4543
4544/**
4545 * \brief Restrict a configuration space to contain only one subformat
4546 * \param pcm PCM handle
4547 * \param params Configuration space
4548 * \param subformat subformat value
4549 * \return 0 otherwise a negative error code if configuration space would become empty
4550 */
4551int snd_pcm_hw_params_set_subformat(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t subformat)
4552{
4553	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_SUBFORMAT, subformat, 0);
4554}
4555
4556/**
4557 * \brief Restrict a configuration space to contain only its first subformat
4558 * \param pcm PCM handle
4559 * \param params Configuration space
4560 * \param subformat Returned subformat
4561 * \return 0 otherwise a negative error code
4562 */
4563#ifndef DOXYGEN
4564EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_subformat_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t *subformat)
4565#else
4566int snd_pcm_hw_params_set_subformat_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t *subformat)
4567#endif
4568{
4569	return snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, (unsigned int *)subformat, NULL);
4570}
4571
4572/**
4573 * \brief Restrict a configuration space to contain only its last subformat
4574 * \param pcm PCM handle
4575 * \param params Configuration space
4576 * \param subformat Returned subformat
4577 * \return 0 otherwise a negative error code
4578 */
4579#ifndef DOXYGEN
4580EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_subformat_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t *subformat)
4581#else
4582int snd_pcm_hw_params_set_subformat_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_t *subformat)
4583#endif
4584{
4585	return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, (unsigned int *)subformat, NULL);
4586}
4587
4588/**
4589 * \brief Restrict a configuration space to contain only a set of subformats
4590 * \param pcm PCM handle
4591 * \param params Configuration space
4592 * \param mask Subformat mask
4593 * \return 0 otherwise a negative error code
4594 */
4595int snd_pcm_hw_params_set_subformat_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask)
4596{
4597	return snd_pcm_hw_param_set_mask(pcm, params, SND_TRY, SND_PCM_HW_PARAM_SUBFORMAT, (snd_mask_t *) mask);
4598}
4599
4600/**
4601 * \brief Get subformat mask from a configuration space
4602 * \param params Configuration space
4603 * \param mask Returned Subformat mask
4604 */
4605void snd_pcm_hw_params_get_subformat_mask(snd_pcm_hw_params_t *params, snd_pcm_subformat_mask_t *mask)
4606{
4607	snd_pcm_subformat_mask_copy(mask, snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_SUBFORMAT));
4608}
4609
4610
4611/**
4612 * \brief Extract channels from a configuration space
4613 * \param params Configuration space
4614 * \param val Returned channels count
4615 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
4616 */
4617#ifndef DOXYGEN
4618EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_channels)(const snd_pcm_hw_params_t *params, unsigned int *val)
4619#else
4620int snd_pcm_hw_params_get_channels(const snd_pcm_hw_params_t *params, unsigned int *val)
4621#endif
4622{
4623	return snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_CHANNELS, val, NULL);
4624}
4625
4626/**
4627 * \brief Extract minimum channels count from a configuration space
4628 * \param params Configuration space
4629 * \param val minimum channels count
4630 * \return 0 otherwise a negative error code
4631 */
4632#ifndef DOXYGEN
4633EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_channels_min)(const snd_pcm_hw_params_t *params, unsigned int *val)
4634#else
4635int snd_pcm_hw_params_get_channels_min(const snd_pcm_hw_params_t *params, unsigned int *val)
4636#endif
4637{
4638	return snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_CHANNELS, val, NULL);
4639}
4640
4641/**
4642 * \brief Extract maximum channels count from a configuration space
4643 * \param params Configuration space
4644 * \param val maximum channels count
4645 * \return 0 otherwise a negative error code
4646 */
4647#ifndef DOXYGEN
4648EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_channels_max)(const snd_pcm_hw_params_t *params, unsigned int *val)
4649#else
4650int snd_pcm_hw_params_get_channels_max(const snd_pcm_hw_params_t *params, unsigned int *val)
4651#endif
4652{
4653	return snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_CHANNELS, val, NULL);
4654}
4655
4656/**
4657 * \brief Verify if a channels count is available inside a configuration space for a PCM
4658 * \param pcm PCM handle
4659 * \param params Configuration space
4660 * \param val channels count
4661 * \return 0 if available a negative error code otherwise
4662 */
4663int snd_pcm_hw_params_test_channels(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
4664{
4665	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_CHANNELS, val, 0);
4666}
4667
4668/**
4669 * \brief Restrict a configuration space to contain only one channels count
4670 * \param pcm PCM handle
4671 * \param params Configuration space
4672 * \param val channels count
4673 * \return 0 otherwise a negative error code if configuration space would become empty
4674 */
4675int snd_pcm_hw_params_set_channels(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
4676{
4677	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_CHANNELS, val, 0);
4678}
4679
4680/**
4681 * \brief Restrict a configuration space with a minimum channels count
4682 * \param pcm PCM handle
4683 * \param params Configuration space
4684 * \param val minimum channels count (on return filled with actual minimum)
4685 * \return 0 otherwise a negative error code if configuration space would become empty
4686 */
4687int snd_pcm_hw_params_set_channels_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4688{
4689	return snd_pcm_hw_param_set_min(pcm, params, SND_TRY, SND_PCM_HW_PARAM_CHANNELS, val, NULL);
4690}
4691
4692/**
4693 * \brief Restrict a configuration space with a maximum channels count
4694 * \param pcm PCM handle
4695 * \param params Configuration space
4696 * \param val maximum channels count (on return filled with actual maximum)
4697 * \return 0 otherwise a negative error code if configuration space would become empty
4698 */
4699int snd_pcm_hw_params_set_channels_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4700{
4701	return snd_pcm_hw_param_set_max(pcm, params, SND_TRY, SND_PCM_HW_PARAM_CHANNELS, val, NULL);
4702}
4703
4704/**
4705 * \brief Restrict a configuration space to have channels counts in a given range
4706 * \param pcm PCM handle
4707 * \param params Configuration space
4708 * \param min minimum channels count (on return filled with actual minimum)
4709 * \param max maximum channels count (on return filled with actual maximum)
4710 * \return 0 otherwise a negative error code if configuration space would become empty
4711 */
4712int snd_pcm_hw_params_set_channels_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *min, unsigned int *max)
4713{
4714	return snd_pcm_hw_param_set_minmax(pcm, params, SND_TRY, SND_PCM_HW_PARAM_CHANNELS, min, NULL, max, NULL);
4715}
4716
4717/**
4718 * \brief Restrict a configuration space to have channels count nearest to a target
4719 * \param pcm PCM handle
4720 * \param params Configuration space
4721 * \param val target channels count, returned chosen channels count
4722 * \return 0 otherwise a negative error code if configuration space is empty
4723 */
4724#ifndef DOXYGEN
4725EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_channels_near)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4726#else
4727int snd_pcm_hw_params_set_channels_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4728#endif
4729{
4730	return snd_pcm_hw_param_set_near(pcm, params, SND_PCM_HW_PARAM_CHANNELS, val, NULL);
4731}
4732
4733/**
4734 * \brief Restrict a configuration space to contain only its minimum channels count
4735 * \param pcm PCM handle
4736 * \param params Configuration space
4737 * \param val minimum channels count
4738 * \return 0 otherwise a negative error code
4739 */
4740#ifndef DOXYGEN
4741EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_channels_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4742#else
4743int snd_pcm_hw_params_set_channels_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4744#endif
4745{
4746	return snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS, val, NULL);
4747}
4748
4749/**
4750 * \brief Restrict a configuration space to contain only its maximum channels count
4751 * \param pcm PCM handle
4752 * \param params Configuration space
4753 * \param val maximum channels count
4754 * \return 0 otherwise a negative error code
4755 */
4756#ifndef DOXYGEN
4757EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_channels_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4758#else
4759int snd_pcm_hw_params_set_channels_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4760#endif
4761{
4762	return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_CHANNELS, val, NULL);
4763}
4764
4765
4766/**
4767 * \brief Extract rate from a configuration space
4768 * \param params Configuration space
4769 * \param val Returned approximate rate
4770 * \param dir Sub unit direction
4771 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
4772 *
4773 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
4774 */
4775#ifndef DOXYGEN
4776EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_rate)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4777#else
4778int snd_pcm_hw_params_get_rate(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4779#endif
4780{
4781	return snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_RATE, val, dir);
4782}
4783
4784/**
4785 * \brief Extract minimum rate from a configuration space
4786 * \param params Configuration space
4787 * \param val Returned approximate minimum rate
4788 * \param dir Sub unit direction
4789 * \return 0 otherwise a negative error code
4790 *
4791 * Exact value is <,=,> the returned one following dir (-1,0,1)
4792 */
4793#ifndef DOXYGEN
4794EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_rate_min)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4795#else
4796int snd_pcm_hw_params_get_rate_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4797#endif
4798{
4799	return snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_RATE, val, dir);
4800}
4801
4802/**
4803 * \brief Extract maximum rate from a configuration space
4804 * \param params Configuration space
4805 * \param val Returned approximate maximum rate
4806 * \param dir Sub unit direction
4807 * \return 0 otherwise a negative error code
4808 *
4809 * Exact value is <,=,> the returned one following dir (-1,0,1)
4810 */
4811#ifndef DOXYGEN
4812EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_rate_max)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4813#else
4814int snd_pcm_hw_params_get_rate_max(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4815#endif
4816{
4817	return snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_RATE, val, dir);
4818}
4819
4820/**
4821 * \brief Verify if a rate is available inside a configuration space for a PCM
4822 * \param pcm PCM handle
4823 * \param params Configuration space
4824 * \param val approximate rate
4825 * \param dir Sub unit direction
4826 * \return 0 if available a negative error code otherwise
4827 *
4828 * Wanted exact value is <,=,> val following dir (-1,0,1)
4829 */
4830int snd_pcm_hw_params_test_rate(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
4831{
4832	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_RATE, val, dir);
4833}
4834
4835/**
4836 * \brief Restrict a configuration space to contain only one rate
4837 * \param pcm PCM handle
4838 * \param params Configuration space
4839 * \param val approximate rate
4840 * \param dir Sub unit direction
4841 * \return 0 otherwise a negative error code if configuration space would become empty
4842 *
4843 * Wanted exact value is <,=,> val following dir (-1,0,1)
4844 */
4845int snd_pcm_hw_params_set_rate(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
4846{
4847	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_RATE, val, dir);
4848}
4849
4850/**
4851 * \brief Restrict a configuration space with a minimum rate
4852 * \param pcm PCM handle
4853 * \param params Configuration space
4854 * \param val approximate minimum rate (on return filled with actual minimum)
4855 * \param dir Sub unit direction (on return filled with actual direction)
4856 * \return 0 otherwise a negative error code if configuration space would become empty
4857 *
4858 * Wanted/actual exact minimum is <,=,> val following dir (-1,0,1)
4859 */
4860int snd_pcm_hw_params_set_rate_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4861{
4862	return snd_pcm_hw_param_set_min(pcm, params, SND_TRY, SND_PCM_HW_PARAM_RATE, val, dir);
4863}
4864
4865/**
4866 * \brief Restrict a configuration space with a maximum rate
4867 * \param pcm PCM handle
4868 * \param params Configuration space
4869 * \param val approximate maximum rate (on return filled with actual maximum)
4870 * \param dir Sub unit direction (on return filled with actual direction)
4871 * \return 0 otherwise a negative error code if configuration space would become empty
4872 *
4873 * Wanted/actual exact maximum is <,=,> val following dir (-1,0,1)
4874 */
4875int snd_pcm_hw_params_set_rate_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4876{
4877	return snd_pcm_hw_param_set_max(pcm, params, SND_TRY, SND_PCM_HW_PARAM_RATE, val, dir);
4878}
4879
4880/**
4881 * \brief Restrict a configuration space to have rates in a given range
4882 * \param pcm PCM handle
4883 * \param params Configuration space
4884 * \param min approximate minimum rate (on return filled with actual minimum)
4885 * \param mindir Sub unit direction for minimum (on return filled with actual direction)
4886 * \param max approximate maximum rate (on return filled with actual maximum)
4887 * \param maxdir Sub unit direction for maximum (on return filled with actual direction)
4888 * \return 0 otherwise a negative error code if configuration space would become empty
4889 *
4890 * Wanted/actual exact min/max is <,=,> val following dir (-1,0,1)
4891 */
4892int snd_pcm_hw_params_set_rate_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *min, int *mindir, unsigned int *max, int *maxdir)
4893{
4894	return snd_pcm_hw_param_set_minmax(pcm, params, SND_TRY, SND_PCM_HW_PARAM_RATE, min, mindir, max, maxdir);
4895}
4896
4897/**
4898 * \brief Restrict a configuration space to have rate nearest to a target
4899 * \param pcm PCM handle
4900 * \param params Configuration space
4901 * \param val approximate target rate / returned approximate set rate
4902 * \param dir Sub unit direction
4903 * \return 0 otherwise a negative error code if configuration space is empty
4904 *
4905 * target/chosen exact value is <,=,> val following dir (-1,0,1)
4906 */
4907#ifndef DOXYGEN
4908EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_rate_near)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4909#else
4910int snd_pcm_hw_params_set_rate_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4911#endif
4912{
4913	return snd_pcm_hw_param_set_near(pcm, params, SND_PCM_HW_PARAM_RATE, val, dir);
4914}
4915
4916/**
4917 * \brief Restrict a configuration space to contain only its minimum rate
4918 * \param pcm PCM handle
4919 * \param params Configuration space
4920 * \param val Returned minimum approximate rate
4921 * \param dir Sub unit direction
4922 * \return 0 otherwise a negative error code
4923 *
4924 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
4925 */
4926#ifndef DOXYGEN
4927EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_rate_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4928#else
4929int snd_pcm_hw_params_set_rate_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4930#endif
4931{
4932	return snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_RATE, val, dir);
4933}
4934
4935/**
4936 * \brief Restrict a configuration space to contain only its maximum rate
4937 * \param pcm PCM handle
4938 * \param params Configuration space
4939 * \param val Returned maximum approximate rate
4940 * \param dir Sub unit direction
4941 * \return 0 otherwise a negative error code
4942 *
4943 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
4944 */
4945#ifndef DOXYGEN
4946EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_rate_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4947#else
4948int snd_pcm_hw_params_set_rate_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
4949#endif
4950{
4951	return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_RATE, val, dir);
4952}
4953
4954/**
4955 * \brief Restrict a configuration space to contain only real hardware rates
4956 * \param pcm PCM handle
4957 * \param params Configuration space
4958 * \param val 0 = disable, 1 = enable (default) rate resampling
4959 * \return 0 otherwise a negative error code
4960 */
4961int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
4962{
4963	assert(pcm && params);
4964	if (!val)
4965		params->flags |= SND_PCM_HW_PARAMS_NORESAMPLE;
4966	else
4967		params->flags &= ~SND_PCM_HW_PARAMS_NORESAMPLE;
4968	params->rmask = ~0;
4969	return snd_pcm_hw_refine(pcm, params);
4970}
4971
4972/**
4973 * \brief Extract resample state from a configuration space
4974 * \param pcm PCM handle
4975 * \param params Configuration space
4976 * \param val 0 = disable, 1 = enable rate resampling
4977 * \return 0 otherwise a negative error code
4978 */
4979int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
4980{
4981	assert(pcm && params && val);
4982	*val = params->flags & SND_PCM_HW_PARAMS_NORESAMPLE ? 0 : 1;
4983	return 0;
4984}
4985
4986/**
4987 * \brief Restrict a configuration space to allow the buffer to be accessible from outside
4988 * \param pcm PCM handle
4989 * \param params Configuration space
4990 * \param val 0 = disable, 1 = enable (default) exporting buffer
4991 * \return 0 otherwise a negative error code
4992 */
4993int snd_pcm_hw_params_set_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
4994{
4995	assert(pcm && params);
4996	if (val)
4997		params->flags |= SND_PCM_HW_PARAMS_EXPORT_BUFFER;
4998	else
4999		params->flags &= ~SND_PCM_HW_PARAMS_EXPORT_BUFFER;
5000	params->rmask = ~0;
5001	return snd_pcm_hw_refine(pcm, params);
5002}
5003
5004/**
5005 * \brief Extract buffer accessibility from a configuration space
5006 * \param pcm PCM handle
5007 * \param params Configuration space
5008 * \param val 0 = disable, 1 = enable exporting buffer
5009 * \return 0 otherwise a negative error code
5010 */
5011int snd_pcm_hw_params_get_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
5012{
5013	assert(pcm && params && val);
5014	*val = params->flags & SND_PCM_HW_PARAMS_EXPORT_BUFFER ? 1 : 0;
5015	return 0;
5016}
5017
5018/**
5019 * \brief Restrict a configuration space to settings without period wakeups
5020 * \param pcm PCM handle
5021 * \param params Configuration space
5022 * \param val 0 = disable, 1 = enable (default) period wakeup
5023 * \return Zero on success, otherwise a negative error code.
5024 *
5025 * This function must be called only on devices where non-blocking mode is
5026 * enabled.
5027 *
5028 * To check whether the hardware does support disabling period wakeups, call
5029 * #snd_pcm_hw_params_can_disable_period_wakeup(). If the hardware does not
5030 * support this mode, standard period wakeups will be generated.
5031 *
5032 * Even with disabled period wakeups, the period size/time/count parameters
5033 * are valid; it is suggested to use #snd_pcm_hw_params_set_period_size_last().
5034 *
5035 * When period wakeups are disabled, the application must not use any functions
5036 * that could block on this device. The use of poll should be limited to error
5037 * cases. The application needs to use an external event or a timer to
5038 * check the state of the ring buffer and refill it apropriately.
5039 */
5040int snd_pcm_hw_params_set_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
5041{
5042	assert(pcm && params);
5043
5044	if (!val) {
5045		if (!(pcm->mode & SND_PCM_NONBLOCK))
5046			return -EINVAL;
5047		params->flags |= SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;
5048	} else
5049		params->flags &= ~SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;
5050	params->rmask = ~0;
5051
5052	return snd_pcm_hw_refine(pcm, params);
5053}
5054
5055/**
5056 * \brief Extract period wakeup flag from a configuration space
5057 * \param pcm PCM handle
5058 * \param params Configuration space
5059 * \param val 0 = disabled, 1 = enabled period wakeups
5060 * \return Zero on success, otherwise a negative error code.
5061 */
5062int snd_pcm_hw_params_get_period_wakeup(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
5063{
5064	assert(pcm && params && val);
5065	*val = params->flags & SND_PCM_HW_PARAMS_NO_PERIOD_WAKEUP ? 0 : 1;
5066	return 0;
5067}
5068
5069/**
5070 * \brief Restrict a configuration space to fill the end of playback stream with silence when drain() is invoked
5071 * \param pcm PCM handle
5072 * \param params Configuration space
5073 * \param val 0 = disabled, 1 = enabled (default) fill the end of the playback stream with silence when drain() is invoked
5074 * \return Zero on success, otherwise a negative error code.
5075 *
5076 * When disabled, the application should handle the end of stream gracefully
5077 * (fill the silent samples to align to the period size plus some extra
5078 * samples for hardware / driver without perfect drain). Note that the rewind
5079 * may be used for this purpose or the sw_params silencing mechanism.
5080 */
5081int snd_pcm_hw_params_set_drain_silence(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
5082{
5083	assert(pcm && params);
5084	if (val)
5085		params->flags &= ~SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE;
5086	else
5087		params->flags |= SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE;
5088	params->rmask = ~0;
5089	return snd_pcm_hw_refine(pcm, params);
5090}
5091
5092/**
5093 * \brief Extract drain with the filling of silence samples from a configuration space
5094 * \param pcm PCM handle
5095 * \param params Configuration space
5096 * \param val 0 = disabled, 1 = enabled
5097 * \return 0 otherwise a negative error code
5098 */
5099int snd_pcm_hw_params_get_drain_silence(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
5100{
5101	assert(pcm && params && val);
5102	*val = params->flags & SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE ? 0 : 1;
5103	return 0;
5104}
5105
5106/**
5107 * \brief Extract period time from a configuration space
5108 * \param params Configuration space
5109 * \param val Returned approximate period duration in us
5110 * \param dir Sub unit direction
5111 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
5112 *
5113 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5114 */
5115#ifndef DOXYGEN
5116EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_period_time)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5117#else
5118int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5119#endif
5120{
5121	return snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5122}
5123
5124/**
5125 * \brief Extract minimum period time from a configuration space
5126 * \param params Configuration space
5127 * \param val approximate minimum period duration in us
5128 * \param dir Sub unit direction
5129 * \return 0 otherwise a negative error code
5130 *
5131 * Exact value is <,=,> the returned one following dir (-1,0,1)
5132 */
5133#ifndef DOXYGEN
5134EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_period_time_min)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5135#else
5136int snd_pcm_hw_params_get_period_time_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5137#endif
5138{
5139	return snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5140}
5141
5142/**
5143 * \brief Extract maximum period time from a configuration space
5144 * \param params Configuration space
5145 * \param val approximate maximum period duration in us
5146 * \param dir Sub unit direction
5147 * \return 0 otherwise a negative error code
5148 *
5149 * Exact value is <,=,> the returned one following dir (-1,0,1)
5150 */
5151#ifndef DOXYGEN
5152EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_period_time_max)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5153#else
5154int snd_pcm_hw_params_get_period_time_max(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5155#endif
5156{
5157	return snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5158}
5159
5160/**
5161 * \brief Verify if a period time is available inside a configuration space for a PCM
5162 * \param pcm PCM handle
5163 * \param params Configuration space
5164 * \param val approximate period duration in us
5165 * \param dir Sub unit direction
5166 * \return 0 if available a negative error code otherwise
5167 *
5168 * Wanted exact value is <,=,> val following dir (-1,0,1)
5169 */
5170int snd_pcm_hw_params_test_period_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
5171{
5172	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5173}
5174
5175/**
5176 * \brief Restrict a configuration space to contain only one period time
5177 * \param pcm PCM handle
5178 * \param params Configuration space
5179 * \param val approximate period duration in us
5180 * \param dir Sub unit direction
5181 * \return 0 otherwise a negative error code if configuration space would become empty
5182 *
5183 * Wanted exact value is <,=,> val following dir (-1,0,1)
5184 */
5185int snd_pcm_hw_params_set_period_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
5186{
5187	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5188}
5189
5190
5191/**
5192 * \brief Restrict a configuration space with a minimum period time
5193 * \param pcm PCM handle
5194 * \param params Configuration space
5195 * \param val approximate minimum period duration in us (on return filled with actual minimum)
5196 * \param dir Sub unit direction (on return filled with actual direction)
5197 * \return 0 otherwise a negative error code if configuration space would become empty
5198 *
5199 * Wanted/actual exact minimum is <,=,> val following dir (-1,0,1)
5200 */
5201int snd_pcm_hw_params_set_period_time_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5202{
5203	return snd_pcm_hw_param_set_min(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5204}
5205
5206/**
5207 * \brief Restrict a configuration space with a maximum period time
5208 * \param pcm PCM handle
5209 * \param params Configuration space
5210 * \param val approximate maximum period duration in us (on return filled with actual maximum)
5211 * \param dir Sub unit direction (on return filled with actual direction)
5212 * \return 0 otherwise a negative error code if configuration space would become empty
5213 *
5214 * Wanted/actual exact maximum is <,=,> val following dir (-1,0,1)
5215 */
5216int snd_pcm_hw_params_set_period_time_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5217{
5218	return snd_pcm_hw_param_set_max(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5219}
5220
5221/**
5222 * \brief Restrict a configuration space to have period times in a given range
5223 * \param pcm PCM handle
5224 * \param params Configuration space
5225 * \param min approximate minimum period duration in us (on return filled with actual minimum)
5226 * \param mindir Sub unit direction for minimum (on return filled with actual direction)
5227 * \param max approximate maximum period duration in us (on return filled with actual maximum)
5228 * \param maxdir Sub unit direction for maximum (on return filled with actual direction)
5229 * \return 0 otherwise a negative error code if configuration space would become empty
5230 *
5231 * Wanted/actual exact min/max is <,=,> val following dir (-1,0,1)
5232 */
5233int snd_pcm_hw_params_set_period_time_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *min, int *mindir, unsigned int *max, int *maxdir)
5234{
5235	return snd_pcm_hw_param_set_minmax(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_TIME, min, mindir, max, maxdir);
5236}
5237
5238/**
5239 * \brief Restrict a configuration space to have period time nearest to a target
5240 * \param pcm PCM handle
5241 * \param params Configuration space
5242 * \param val approximate target period duration in us / returned chosen approximate target period duration
5243 * \param dir Sub unit direction
5244 * \return 0 otherwise a negative error code if configuration space is empty
5245 *
5246 * target/chosen exact value is <,=,> val following dir (-1,0,1)
5247 */
5248#ifndef DOXYGEN
5249EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_period_time_near)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5250#else
5251int snd_pcm_hw_params_set_period_time_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5252#endif
5253{
5254	return snd_pcm_hw_param_set_near(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5255}
5256
5257/**
5258 * \brief Restrict a configuration space to contain only its minimum period time
5259 * \param pcm PCM handle
5260 * \param params Configuration space
5261 * \param val Returned approximate period duration in us
5262 * \param dir Sub unit direction
5263 * \return 0 otherwise a negative error code
5264 *
5265 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5266 */
5267#ifndef DOXYGEN
5268EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_period_time_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5269#else
5270int snd_pcm_hw_params_set_period_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5271#endif
5272{
5273	return snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5274}
5275
5276/**
5277 * \brief Restrict a configuration space to contain only its maximum period time
5278 * \param pcm PCM handle
5279 * \param params Configuration space
5280 * \param val Returned maximum approximate period time
5281 * \param dir Sub unit direction
5282 * \return approximate period duration in us
5283 */
5284#ifndef DOXYGEN
5285EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_period_time_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5286#else
5287int snd_pcm_hw_params_set_period_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5288#endif
5289{
5290	return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, val, dir);
5291}
5292
5293
5294/**
5295 * \brief Extract period size from a configuration space
5296 * \param params Configuration space
5297 * \param val Returned approximate period size in frames
5298 * \param dir Sub unit direction
5299 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
5300 *
5301 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5302 */
5303#ifndef DOXYGEN
5304EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_period_size)(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5305#else
5306int snd_pcm_hw_params_get_period_size(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5307#endif
5308{
5309	unsigned int _val;
5310	int err = snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_PERIOD_SIZE, &_val, dir);
5311	if (err >= 0)
5312		*val = _val;
5313	return err;
5314}
5315
5316/**
5317 * \brief Extract minimum period size from a configuration space
5318 * \param params Configuration space
5319 * \param val approximate minimum period size in frames
5320 * \param dir Sub unit direction
5321 * \return 0 otherwise a negative error code
5322 *
5323 * Exact value is <,=,> the returned one following dir (-1,0,1)
5324 */
5325#ifndef DOXYGEN
5326EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_period_size_min)(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5327#else
5328int snd_pcm_hw_params_get_period_size_min(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5329#endif
5330{
5331	unsigned int _val = *val;
5332	int err = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_PERIOD_SIZE, &_val, dir);
5333	if (err >= 0)
5334		*val = _val;
5335	return err;
5336}
5337
5338/**
5339 * \brief Extract maximum period size from a configuration space
5340 * \param params Configuration space
5341 * \param val approximate minimum period size in frames
5342 * \param dir Sub unit direction
5343 * \return 0 otherwise a negative error code
5344 *
5345 * Exact value is <,=,> the returned one following dir (-1,0,1)
5346 */
5347#ifndef DOXYGEN
5348EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_period_size_max)(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5349#else
5350int snd_pcm_hw_params_get_period_size_max(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5351#endif
5352{
5353	unsigned int _val = *val;
5354	int err = snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_PERIOD_SIZE, &_val, dir);
5355	if (err >= 0)
5356		*val = _val;
5357	return err;
5358}
5359
5360/**
5361 * \brief Verify if a period size is available inside a configuration space for a PCM
5362 * \param pcm PCM handle
5363 * \param params Configuration space
5364 * \param val approximate period size in frames
5365 * \param dir Sub unit direction
5366 * \return 0 if available a negative error code otherwise
5367 *
5368 * Wanted exact value is <,=,> val following dir (-1,0,1)
5369 */
5370int snd_pcm_hw_params_test_period_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int dir)
5371{
5372	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_PERIOD_SIZE, val, dir);
5373}
5374
5375/**
5376 * \brief Restrict a configuration space to contain only one period size
5377 * \param pcm PCM handle
5378 * \param params Configuration space
5379 * \param val approximate period size in frames
5380 * \param dir Sub unit direction
5381 * \return 0 otherwise a negative error code if configuration space would become empty
5382 *
5383 * Wanted exact value is <,=,> val following dir (-1,0,1)
5384 */
5385int snd_pcm_hw_params_set_period_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int dir)
5386{
5387	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_SIZE, val, dir);
5388}
5389
5390/**
5391 * \brief Restrict a configuration space with a minimum period size
5392 * \param pcm PCM handle
5393 * \param params Configuration space
5394 * \param val approximate minimum period size in frames (on return filled with actual minimum)
5395 * \param dir Sub unit direction (on return filled with actual direction)
5396 * \return 0 otherwise a negative error code if configuration space would become empty
5397 *
5398 * Wanted/actual exact minimum is <,=,> val following dir (-1,0,1)
5399 */
5400int snd_pcm_hw_params_set_period_size_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5401{
5402	unsigned int _val = *val;
5403	int err = snd_pcm_hw_param_set_min(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_SIZE, &_val, dir);
5404	if (err >= 0)
5405		*val = _val;
5406	return err;
5407}
5408
5409/**
5410 * \brief Restrict a configuration space with a maximum period size
5411 * \param pcm PCM handle
5412 * \param params Configuration space
5413 * \param val approximate maximum period size in frames (on return filled with actual maximum)
5414 * \param dir Sub unit direction (on return filled with actual direction)
5415 * \return 0 otherwise a negative error code if configuration space would become empty
5416 *
5417 * Wanted/actual exact minimum is <,=,> val following dir (-1,0,1)
5418 */
5419int snd_pcm_hw_params_set_period_size_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5420{
5421	unsigned int _val = *val;
5422	int err = snd_pcm_hw_param_set_max(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_SIZE, &_val, dir);
5423	if (err >= 0)
5424		*val = _val;
5425	return err;
5426}
5427
5428/**
5429 * \brief Restrict a configuration space to have period sizes in a given range
5430 * \param pcm PCM handle
5431 * \param params Configuration space
5432 * \param min approximate minimum period size in frames (on return filled with actual minimum)
5433 * \param mindir Sub unit direction for minimum (on return filled with actual direction)
5434 * \param max approximate maximum period size in frames (on return filled with actual maximum)
5435 * \param maxdir Sub unit direction for maximum (on return filled with actual direction)
5436 * \return 0 otherwise a negative error code if configuration space would become empty
5437 *
5438 * Wanted/actual exact min/max is <,=,> val following dir (-1,0,1)
5439 */
5440int snd_pcm_hw_params_set_period_size_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *min, int *mindir, snd_pcm_uframes_t *max, int *maxdir)
5441{
5442	unsigned int _min = *min;
5443	unsigned int _max = *max;
5444	int err = snd_pcm_hw_param_set_minmax(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_SIZE, &_min, mindir, &_max, maxdir);
5445	*min = _min;
5446	*max = _max;
5447	return err;
5448}
5449
5450/**
5451 * \brief Restrict a configuration space to have period size nearest to a target
5452 * \param pcm PCM handle
5453 * \param params Configuration space
5454 * \param val approximate target period size in frames / returned chosen approximate target period size
5455 * \param dir Sub unit direction
5456 * \return 0 otherwise a negative error code if configuration space is empty
5457 *
5458 * target/chosen exact value is <,=,> val following dir (-1,0,1)
5459 */
5460#ifndef DOXYGEN
5461EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_period_size_near)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5462#else
5463int snd_pcm_hw_params_set_period_size_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5464#endif
5465{
5466	unsigned int _val = *val;
5467	int err = snd_pcm_hw_param_set_near(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, &_val, dir);
5468	if (err >= 0)
5469		*val = _val;
5470	return err;
5471}
5472
5473/**
5474 * \brief Restrict a configuration space to contain only its minimum period size
5475 * \param pcm PCM handle
5476 * \param params Configuration space
5477 * \param val Returned maximum approximate period size in frames
5478 * \param dir Sub unit direction
5479 * \return 0 otherwise a negative error code
5480 *
5481 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5482 */
5483#ifndef DOXYGEN
5484EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_period_size_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5485#else
5486int snd_pcm_hw_params_set_period_size_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5487#endif
5488{
5489	unsigned int _val;
5490	int err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, &_val, dir);
5491	if (err >= 0)
5492		*val = _val;
5493	return err;
5494}
5495
5496/**
5497 * \brief Restrict a configuration space to contain only its maximum period size
5498 * \param pcm PCM handle
5499 * \param params Configuration space
5500 * \param val Returned maximum approximate period size in frames
5501 * \param dir Sub unit direction
5502 * \return 0 otherwise a negative error code
5503 *
5504 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5505 */
5506#ifndef DOXYGEN
5507EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_period_size_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5508#else
5509int snd_pcm_hw_params_set_period_size_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
5510#endif
5511{
5512	unsigned int _val;
5513	int err = snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, &_val, dir);
5514	if (err >= 0)
5515		*val = _val;
5516	return err;
5517}
5518
5519/**
5520 * \brief Restrict a configuration space to contain only integer period sizes
5521 * \param pcm PCM handle
5522 * \param params Configuration space
5523 * \return 0 otherwise a negative error code if configuration space would become empty
5524 */
5525int snd_pcm_hw_params_set_period_size_integer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
5526{
5527	return snd_pcm_hw_param_set_integer(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIOD_SIZE);
5528}
5529
5530
5531/**
5532 * \brief Extract periods from a configuration space
5533 * \param params Configuration space
5534 * \param val approximate periods per buffer
5535 * \param dir Sub unit direction
5536 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
5537 *
5538 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5539 */
5540#ifndef DOXYGEN
5541EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_periods)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5542#else
5543int snd_pcm_hw_params_get_periods(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5544#endif
5545{
5546	return snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_PERIODS, val, dir);
5547}
5548
5549/**
5550 * \brief Extract minimum periods count from a configuration space
5551 * \param params Configuration space
5552 * \param val approximate minimum periods per buffer
5553 * \param dir Sub unit direction
5554 * \return 0 otherwise a negative error code
5555 *
5556 * Exact value is <,=,> the returned one following dir (-1,0,1)
5557 */
5558#ifndef DOXYGEN
5559EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_periods_min)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5560#else
5561int snd_pcm_hw_params_get_periods_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5562#endif
5563{
5564	return snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_PERIODS, val, dir);
5565}
5566
5567/**
5568 * \brief Extract maximum periods count from a configuration space
5569 * \param params Configuration space
5570 * \param val approximate maximum periods per buffer
5571 * \param dir Sub unit direction
5572 * \return 0 otherwise a negative error code
5573 *
5574 * Exact value is <,=,> the returned one following dir (-1,0,1)
5575 */
5576#ifndef DOXYGEN
5577EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_periods_max)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5578#else
5579int snd_pcm_hw_params_get_periods_max(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5580#endif
5581{
5582	return snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_PERIODS, val, dir);
5583}
5584
5585/**
5586 * \brief Verify if a periods count is available inside a configuration space for a PCM
5587 * \param pcm PCM handle
5588 * \param params Configuration space
5589 * \param val approximate periods per buffer
5590 * \param dir Sub unit direction
5591 * \return 0 if available a negative error code otherwise
5592 *
5593 * Wanted exact value is <,=,> val following dir (-1,0,1)
5594 */
5595int snd_pcm_hw_params_test_periods(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
5596{
5597	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_PERIODS, val, dir);
5598}
5599
5600/**
5601 * \brief Restrict a configuration space to contain only one periods count
5602 * \param pcm PCM handle
5603 * \param params Configuration space
5604 * \param val approximate periods per buffer
5605 * \param dir Sub unit direction
5606 * \return 0 otherwise a negative error code if configuration space would become empty
5607 *
5608 * Wanted exact value is <,=,> val following dir (-1,0,1)
5609 */
5610int snd_pcm_hw_params_set_periods(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
5611{
5612	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIODS, val, dir);
5613}
5614
5615/**
5616 * \brief Restrict a configuration space with a minimum periods count
5617 * \param pcm PCM handle
5618 * \param params Configuration space
5619 * \param val approximate minimum periods per buffer (on return filled with actual minimum)
5620 * \param dir Sub unit direction (on return filled with actual direction)
5621 * \return 0 otherwise a negative error code if configuration space would become empty
5622 *
5623 * Wanted/actual exact minimum is <,=,> val following dir (-1,0,1)
5624 */
5625int snd_pcm_hw_params_set_periods_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5626{
5627	return snd_pcm_hw_param_set_min(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIODS, val, dir);
5628}
5629
5630/**
5631 * \brief Restrict a configuration space with a maximum periods count
5632 * \param pcm PCM handle
5633 * \param params Configuration space
5634 * \param val approximate maximum periods per buffer (on return filled with actual maximum)
5635 * \param dir Sub unit direction (on return filled with actual direction)
5636 * \return 0 otherwise a negative error code if configuration space would become empty
5637 *
5638 * Wanted/actual exact maximum is <,=,> val following dir (-1,0,1)
5639 */
5640int snd_pcm_hw_params_set_periods_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5641{
5642	return snd_pcm_hw_param_set_max(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIODS, val, dir);
5643}
5644
5645/**
5646 * \brief Restrict a configuration space to have periods counts in a given range
5647 * \param pcm PCM handle
5648 * \param params Configuration space
5649 * \param min approximate minimum periods per buffer (on return filled with actual minimum)
5650 * \param mindir Sub unit direction for minimum (on return filled with actual direction)
5651 * \param max approximate maximum periods per buffer (on return filled with actual maximum)
5652 * \param maxdir Sub unit direction for maximum (on return filled with actual direction)
5653 * \return 0 otherwise a negative error code if configuration space would become empty
5654 *
5655 * Wanted/actual exact min/max is <,=,> val following dir (-1,0,1)
5656 */
5657int snd_pcm_hw_params_set_periods_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *min, int *mindir, unsigned int *max, int *maxdir)
5658{
5659	return snd_pcm_hw_param_set_minmax(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIODS, min, mindir, max, maxdir);
5660}
5661
5662/**
5663 * \brief Restrict a configuration space to have periods count nearest to a target
5664 * \param pcm PCM handle
5665 * \param params Configuration space
5666 * \param val approximate target periods per buffer / returned chosen approximate target periods per buffer
5667 * \param dir Sub unit direction
5668 * \return 0 otherwise a negative error code if configuration space is empty
5669 *
5670 * target/chosen exact value is <,=,> val following dir (-1,0,1)
5671 */
5672#ifndef DOXYGEN
5673EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_periods_near)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5674#else
5675int snd_pcm_hw_params_set_periods_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5676#endif
5677{
5678	return snd_pcm_hw_param_set_near(pcm, params, SND_PCM_HW_PARAM_PERIODS, val, dir);
5679}
5680
5681/**
5682 * \brief Restrict a configuration space to contain only its minimum periods count
5683 * \param pcm PCM handle
5684 * \param params Configuration space
5685 * \param val Returned approximate minimum periods per buffer
5686 * \param dir Sub unit direction
5687 * \return 0 otherwise a negative error code
5688 *
5689 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5690 */
5691#ifndef DOXYGEN
5692EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_periods_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5693#else
5694int snd_pcm_hw_params_set_periods_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5695#endif
5696{
5697	return snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIODS, val, dir);
5698}
5699
5700/**
5701 * \brief Restrict a configuration space to contain only its maximum periods count
5702 * \param pcm PCM handle
5703 * \param params Configuration space
5704 * \param val Returned approximate maximum periods per buffer
5705 * \param dir Sub unit direction
5706 * \return 0 otherwise a negative error code
5707 *
5708 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5709 */
5710#ifndef DOXYGEN
5711EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_periods_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5712#else
5713int snd_pcm_hw_params_set_periods_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5714#endif
5715{
5716	return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_PERIODS, val, dir);
5717}
5718
5719/**
5720 * \brief Restrict a configuration space to contain only integer periods counts
5721 * \param pcm PCM handle
5722 * \param params Configuration space
5723 * \return 0 otherwise a negative error code if configuration space would become empty
5724 */
5725int snd_pcm_hw_params_set_periods_integer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
5726{
5727	return snd_pcm_hw_param_set_integer(pcm, params, SND_TRY, SND_PCM_HW_PARAM_PERIODS);
5728}
5729
5730
5731/**
5732 * \brief Extract buffer time from a configuration space
5733 * \param params Configuration space
5734 * \param val Returned buffer time in us
5735 * \param dir Sub unit direction
5736 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
5737 *
5738 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5739 */
5740#ifndef DOXYGEN
5741EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_buffer_time)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5742#else
5743int snd_pcm_hw_params_get_buffer_time(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5744#endif
5745{
5746	return snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5747}
5748
5749/**
5750 * \brief Extract minimum buffer time from a configuration space
5751 * \param params Configuration space
5752 * \param val approximate minimum buffer duration in us
5753 * \param dir Sub unit direction
5754 * \return 0 otherwise a negative error code
5755 *
5756 * Exact value is <,=,> the returned one following dir (-1,0,1)
5757 */
5758#ifndef DOXYGEN
5759EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_buffer_time_min)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5760#else
5761int snd_pcm_hw_params_get_buffer_time_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5762#endif
5763{
5764	return snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5765}
5766
5767/**
5768 * \brief Extract maximum buffer time from a configuration space
5769 * \param params Configuration space
5770 * \param val approximate maximum buffer duration in us
5771 * \param dir Sub unit direction
5772 * \return 0 otherwise a negative error code
5773 *
5774 * Exact value is <,=,> the returned one following dir (-1,0,1)
5775 */
5776#ifndef DOXYGEN
5777EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_buffer_time_max)(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5778#else
5779int snd_pcm_hw_params_get_buffer_time_max(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5780#endif
5781{
5782	return snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5783}
5784
5785/**
5786 * \brief Verify if a buffer time is available inside a configuration space for a PCM
5787 * \param pcm PCM handle
5788 * \param params Configuration space
5789 * \param val approximate buffer duration in us
5790 * \param dir Sub unit direction
5791 * \return 0 if available a negative error code otherwise
5792 *
5793 * Wanted exact value is <,=,> val following dir (-1,0,1)
5794 */
5795int snd_pcm_hw_params_test_buffer_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
5796{
5797	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5798}
5799
5800/**
5801 * \brief Restrict a configuration space to contain only one buffer time
5802 * \param pcm PCM handle
5803 * \param params Configuration space
5804 * \param val approximate buffer duration in us
5805 * \param dir Sub unit direction
5806 * \return 0 otherwise a negative error code if configuration space would become empty
5807 *
5808 * Wanted exact value is <,=,> val following dir (-1,0,1)
5809 */
5810int snd_pcm_hw_params_set_buffer_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)
5811{
5812	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5813}
5814
5815/**
5816 * \brief Restrict a configuration space with a minimum buffer time
5817 * \param pcm PCM handle
5818 * \param params Configuration space
5819 * \param val approximate minimum buffer duration in us (on return filled with actual minimum)
5820 * \param dir Sub unit direction (on return filled with actual direction)
5821 * \return 0 otherwise a negative error code if configuration space would become empty
5822 *
5823 * Wanted/actual exact minimum is <,=,> val following dir (-1,0,1)
5824 */
5825int snd_pcm_hw_params_set_buffer_time_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5826{
5827	return snd_pcm_hw_param_set_min(pcm, params, SND_TRY, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5828}
5829
5830/**
5831 * \brief Restrict a configuration space with a maximum buffer time
5832 * \param pcm PCM handle
5833 * \param params Configuration space
5834 * \param val approximate maximum buffer duration in us (on return filled with actual maximum)
5835 * \param dir Sub unit direction (on return filled with actual direction)
5836 * \return 0 otherwise a negative error code if configuration space would become empty
5837 *
5838 * Wanted/actual exact maximum is <,=,> val following dir (-1,0,1)
5839 */
5840int snd_pcm_hw_params_set_buffer_time_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5841{
5842	return snd_pcm_hw_param_set_max(pcm, params, SND_TRY, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5843}
5844
5845/**
5846 * \brief Restrict a configuration space to have buffer times in a given range
5847 * \param pcm PCM handle
5848 * \param params Configuration space
5849 * \param min approximate minimum buffer duration in us (on return filled with actual minimum)
5850 * \param mindir Sub unit direction for minimum (on return filled with actual direction)
5851 * \param max approximate maximum buffer duration in us (on return filled with actual maximum)
5852 * \param maxdir Sub unit direction for maximum (on return filled with actual direction)
5853 * \return 0 otherwise a negative error code if configuration space would become empty
5854 *
5855 * Wanted/actual exact min/max is <,=,> val following dir (-1,0,1)
5856 */
5857int snd_pcm_hw_params_set_buffer_time_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *min, int *mindir, unsigned int *max, int *maxdir)
5858{
5859	return snd_pcm_hw_param_set_minmax(pcm, params, SND_TRY, SND_PCM_HW_PARAM_BUFFER_TIME, min, mindir, max, maxdir);
5860}
5861
5862/**
5863 * \brief Restrict a configuration space to have buffer time nearest to a target
5864 * \param pcm PCM handle
5865 * \param params Configuration space
5866 * \param val approximate target buffer duration in us / returned chosen approximate target buffer duration
5867 * \param dir Sub unit direction
5868 * \return 0 otherwise a negative error code if configuration space is empty
5869 *
5870 * target/chosen exact value is <,=,> val following dir (-1,0,1)
5871 */
5872#ifndef DOXYGEN
5873EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_buffer_time_near)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5874#else
5875int snd_pcm_hw_params_set_buffer_time_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5876#endif
5877{
5878	return snd_pcm_hw_param_set_near(pcm, params, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5879}
5880
5881/**
5882 * \brief Restrict a configuration space to contain only its minimum buffer time
5883 * \param pcm PCM handle
5884 * \param params Configuration space
5885 * \param val Returned approximate minimum buffer duration in us
5886 * \param dir Sub unit direction
5887 * \return 0 otherwise a negative error code
5888 *
5889 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5890 */
5891#ifndef DOXYGEN
5892EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_buffer_time_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5893#else
5894int snd_pcm_hw_params_set_buffer_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5895#endif
5896{
5897	return snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5898}
5899
5900/**
5901 * \brief Restrict a configuration space to contain only its maximum buffered time
5902 * \param pcm PCM handle
5903 * \param params Configuration space
5904 * \param val Returned approximate maximum buffer duration in us
5905 * \param dir Sub unit direction
5906 * \return 0 otherwise a negative error code
5907 *
5908 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
5909 */
5910#ifndef DOXYGEN
5911EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_buffer_time_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5912#else
5913int snd_pcm_hw_params_set_buffer_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
5914#endif
5915{
5916	return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_TIME, val, dir);
5917}
5918
5919
5920/**
5921 * \brief Extract buffer size from a configuration space
5922 * \param params Configuration space
5923 * \param val Returned buffer size in frames
5924 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
5925 */
5926#ifndef DOXYGEN
5927EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_buffer_size)(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
5928#else
5929int snd_pcm_hw_params_get_buffer_size(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
5930#endif
5931{
5932	unsigned int _val;
5933	int err = snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_BUFFER_SIZE, &_val, NULL);
5934	if (err >= 0)
5935		*val = _val;
5936	return err;
5937}
5938
5939/**
5940 * \brief Extract minimum buffer size from a configuration space
5941 * \param params Configuration space
5942 * \param val Returned approximate minimum buffer size in frames
5943 * \return 0 otherwise a negative error code
5944 */
5945#ifndef DOXYGEN
5946EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_buffer_size_min)(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
5947#else
5948int snd_pcm_hw_params_get_buffer_size_min(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
5949#endif
5950{
5951	unsigned int _val;
5952	int err = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_BUFFER_SIZE, &_val, NULL);
5953	if (err >= 0)
5954		*val = _val;
5955	return err;
5956}
5957
5958/**
5959 * \brief Extract maximum buffer size from a configuration space
5960 * \param params Configuration space
5961 * \param val Returned approximate maximum buffer size in frames
5962 * \return 0 otherwise a negative error code
5963 *
5964 * Exact value is <,=,> the returned one following dir (-1,0,1)
5965 */
5966#ifndef DOXYGEN
5967EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_buffer_size_max)(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
5968#else
5969int snd_pcm_hw_params_get_buffer_size_max(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
5970#endif
5971{
5972	unsigned int _val;
5973	int err = snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_BUFFER_SIZE, &_val, NULL);
5974	if (err >= 0)
5975		*val = _val;
5976	return err;
5977}
5978
5979/**
5980 * \brief Verify if a buffer size is available inside a configuration space for a PCM
5981 * \param pcm PCM handle
5982 * \param params Configuration space
5983 * \param val buffer size in frames
5984 * \return 0 if available a negative error code otherwise
5985 *
5986 * Wanted exact value is <,=,> val following dir (-1,0,1)
5987 */
5988int snd_pcm_hw_params_test_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val)
5989{
5990	return snd_pcm_hw_param_set(pcm, params, SND_TEST, SND_PCM_HW_PARAM_BUFFER_SIZE, val, 0);
5991}
5992
5993/**
5994 * \brief Restrict a configuration space to contain only one buffer size
5995 * \param pcm PCM handle
5996 * \param params Configuration space
5997 * \param val buffer size in frames
5998 * \return 0 otherwise a negative error code if configuration space would become empty
5999 *
6000 * Wanted exact value is <,=,> val following dir (-1,0,1)
6001 */
6002int snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val)
6003{
6004	return snd_pcm_hw_param_set(pcm, params, SND_TRY, SND_PCM_HW_PARAM_BUFFER_SIZE, val, 0);
6005}
6006
6007/**
6008 * \brief Restrict a configuration space with a minimum buffer size
6009 * \param pcm PCM handle
6010 * \param params Configuration space
6011 * \param val approximate minimum buffer size in frames (on return filled with actual minimum)
6012 * \return 0 otherwise a negative error code if configuration space would become empty
6013 */
6014int snd_pcm_hw_params_set_buffer_size_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6015{
6016	unsigned int _val = *val;
6017	int err = snd_pcm_hw_param_set_min(pcm, params, SND_TRY, SND_PCM_HW_PARAM_BUFFER_SIZE, &_val, NULL);
6018	if (err >= 0)
6019		*val = _val;
6020	return err;
6021}
6022
6023/**
6024 * \brief Restrict a configuration space with a maximum buffer size
6025 * \param pcm PCM handle
6026 * \param params Configuration space
6027 * \param val approximate maximum buffer size in frames (on return filled with actual maximum)
6028 * \return 0 otherwise a negative error code if configuration space would become empty
6029 */
6030int snd_pcm_hw_params_set_buffer_size_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6031{
6032	unsigned int _val = *val;
6033	int err = snd_pcm_hw_param_set_max(pcm, params, SND_TRY, SND_PCM_HW_PARAM_BUFFER_SIZE, &_val, NULL);
6034	if (err >= 0)
6035		*val = _val;
6036	return err;
6037}
6038
6039/**
6040 * \brief Restrict a configuration space to have buffer sizes in a given range
6041 * \param pcm PCM handle
6042 * \param params Configuration space
6043 * \param min approximate minimum buffer size in frames (on return filled with actual minimum)
6044 * \param max approximate maximum buffer size in frames (on return filled with actual maximum)
6045 * \return 0 otherwise a negative error code if configuration space would become empty
6046 */
6047int snd_pcm_hw_params_set_buffer_size_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *min, snd_pcm_uframes_t *max)
6048{
6049	unsigned int _min = *min;
6050	unsigned int _max = *max;
6051	int err = snd_pcm_hw_param_set_minmax(pcm, params, SND_TRY, SND_PCM_HW_PARAM_BUFFER_SIZE, &_min, NULL, &_max, NULL);
6052	*min = _min;
6053	*max = _max;
6054	return err;
6055}
6056
6057/**
6058 * \brief Restrict a configuration space to have buffer size nearest to a target
6059 * \param pcm PCM handle
6060 * \param params Configuration space
6061 * \param val approximate target buffer size in frames / returned chosen approximate target buffer size in frames
6062 * \return 0 otherwise a negative error code if configuration space is empty
6063 */
6064#ifndef DOXYGEN
6065EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_buffer_size_near)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6066#else
6067int snd_pcm_hw_params_set_buffer_size_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6068#endif
6069{
6070	unsigned int _val = *val;
6071	int err = snd_pcm_hw_param_set_near(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, &_val, NULL);
6072	if (err >= 0)
6073		*val = _val;
6074	return err;
6075}
6076
6077/**
6078 * \brief Restrict a configuration space to contain only its minimum buffer size
6079 * \param pcm PCM handle
6080 * \param params Configuration space
6081 * \param val Returned minimum buffer size in frames
6082 * \return buffer size in frames
6083 */
6084#ifndef DOXYGEN
6085EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_buffer_size_first)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6086#else
6087int snd_pcm_hw_params_set_buffer_size_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6088#endif
6089{
6090	unsigned int _val;
6091	int err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, &_val, NULL);
6092	if (err >= 0)
6093		*val = _val;
6094	return err;
6095}
6096
6097/**
6098 * \brief Restrict a configuration space to contain only its maximum buffer size
6099 * \param pcm PCM handle
6100 * \param params Configuration space
6101 * \param val Returned maximum buffer size in frames
6102 * \return 0 otherwise a negative error code
6103 */
6104#ifndef DOXYGEN
6105EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_buffer_size_last)(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6106#else
6107int snd_pcm_hw_params_set_buffer_size_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6108#endif
6109{
6110	unsigned int _val;
6111	int err = snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, &_val, NULL);
6112	if (err >= 0)
6113		*val = _val;
6114	return err;
6115}
6116
6117
6118/**
6119 * \brief (DEPRECATED) Extract tick time from a configuration space
6120 * \param params Configuration space
6121 * \param val Returned approximate tick duration in us
6122 * \param dir Sub unit direction
6123 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
6124 *
6125 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
6126 */
6127#ifndef DOXYGEN
6128EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_tick_time)(const snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val, int *dir ATTRIBUTE_UNUSED)
6129#else
6130int snd_pcm_hw_params_get_tick_time(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
6131#endif
6132{
6133	*val = 0;
6134	return 0;
6135}
6136
6137/**
6138 * \brief (DEPRECATED) Extract minimum tick time from a configuration space
6139 * \param params Configuration space
6140 * \param val Returned approximate minimum tick duration in us
6141 * \param dir Sub unit direction
6142 * \return 0 otherwise a negative error code
6143 *
6144 * Exact value is <,=,> the returned one following dir (-1,0,1)
6145 */
6146#ifndef DOXYGEN
6147EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_tick_time_min)(const snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val, int *dir ATTRIBUTE_UNUSED)
6148#else
6149int snd_pcm_hw_params_get_tick_time_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
6150#endif
6151{
6152	*val = 0;
6153	return 0;
6154}
6155
6156/**
6157 * \brief (DEPRECATED) Extract maximum tick time from a configuration space
6158 * \param params Configuration space
6159 * \param val Returned approximate maximum tick duration in us
6160 * \param dir Sub unit direction
6161 * \return 0 otherwise a negative error code
6162 *
6163 * Exact value is <,=,> the returned one following dir (-1,0,1)
6164 */
6165#ifndef DOXYGEN
6166EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_get_tick_time_max)(const snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val, int *dir ATTRIBUTE_UNUSED)
6167#else
6168int snd_pcm_hw_params_get_tick_time_max(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
6169#endif
6170{
6171	*val = 0;
6172	return 0;
6173}
6174
6175/**
6176 * \brief (DEPRECATED) Verify if a tick time is available inside a configuration space for a PCM
6177 * \param pcm PCM handle
6178 * \param params Configuration space
6179 * \param val approximate tick duration in us
6180 * \param dir Sub unit direction
6181 * \return 0 if available a negative error code otherwise
6182 *
6183 * Wanted exact value is <,=,> val following dir (-1,0,1)
6184 */
6185int snd_pcm_hw_params_test_tick_time(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int val, int dir ATTRIBUTE_UNUSED)
6186{
6187	return val ? -EINVAL : 0;
6188}
6189
6190/**
6191 * \brief (DEPRECATED) Restrict a configuration space to contain only one tick time
6192 * \param pcm PCM handle
6193 * \param params Configuration space
6194 * \param val approximate tick duration in us
6195 * \param dir Sub unit direction
6196 * \return 0 otherwise a negative error code if configuration space would become empty
6197 *
6198 * Wanted exact value is <,=,> val following dir (-1,0,1)
6199 */
6200int snd_pcm_hw_params_set_tick_time(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int val ATTRIBUTE_UNUSED, int dir ATTRIBUTE_UNUSED)
6201{
6202	return 0;
6203}
6204
6205/**
6206 * \brief (DEPRECATED) Restrict a configuration space with a minimum tick time
6207 * \param pcm PCM handle
6208 * \param params Configuration space
6209 * \param val approximate minimum tick duration in us (on return filled with actual minimum)
6210 * \param dir Sub unit direction (on return filled with actual direction)
6211 * \return 0 otherwise a negative error code if configuration space would become empty
6212 *
6213 * Wanted/actual exact minimum is <,=,> val following dir (-1,0,1)
6214 */
6215int snd_pcm_hw_params_set_tick_time_min(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val ATTRIBUTE_UNUSED, int *dir ATTRIBUTE_UNUSED)
6216{
6217	return 0;
6218}
6219
6220/**
6221 * \brief (DEPRECATED) Restrict a configuration space with a maximum tick time
6222 * \param pcm PCM handle
6223 * \param params Configuration space
6224 * \param val approximate maximum tick duration in us (on return filled with actual maximum)
6225 * \param dir Sub unit direction (on return filled with actual direction)
6226 * \return 0 otherwise a negative error code if configuration space would become empty
6227 *
6228 * Wanted/actual exact maximum is <,=,> val following dir (-1,0,1)
6229 */
6230int snd_pcm_hw_params_set_tick_time_max(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val ATTRIBUTE_UNUSED, int *dir ATTRIBUTE_UNUSED)
6231{
6232	return 0;
6233}
6234
6235/**
6236 * \brief (DEPRECATED) Restrict a configuration space to have tick times in a given range
6237 * \param pcm PCM handle
6238 * \param params Configuration space
6239 * \param min approximate minimum tick duration in us (on return filled with actual minimum)
6240 * \param mindir Sub unit direction for minimum (on return filled with actual direction)
6241 * \param max approximate maximum tick duration in us (on return filled with actual maximum)
6242 * \param maxdir Sub unit direction for maximum (on return filled with actual direction)
6243 * \return 0 otherwise a negative error code if configuration space would become empty
6244 *
6245 * Wanted/actual exact min/max is <,=,> val following dir (-1,0,1)
6246 */
6247int snd_pcm_hw_params_set_tick_time_minmax(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *min ATTRIBUTE_UNUSED, int *mindir ATTRIBUTE_UNUSED, unsigned int *max ATTRIBUTE_UNUSED, int *maxdir ATTRIBUTE_UNUSED)
6248{
6249	return 0;
6250}
6251
6252/**
6253 * \brief (DEPRECATED) Restrict a configuration space to have tick time nearest to a target
6254 * \param pcm PCM handle
6255 * \param params Configuration space
6256 * \param val approximate target tick duration in us / returned chosen approximate target tick duration in us
6257 * \param dir Sub unit direction
6258 * \return 0 otherwise a negative error code if configuration space is empty
6259 *
6260 * target/chosen exact value is <,=,> val following dir (-1,0,1)
6261 */
6262#ifndef DOXYGEN
6263EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_tick_time_near)(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val ATTRIBUTE_UNUSED, int *dir ATTRIBUTE_UNUSED)
6264#else
6265int snd_pcm_hw_params_set_tick_time_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
6266#endif
6267{
6268	return 0;
6269}
6270
6271/**
6272 * \brief (DEPRECATED) Restrict a configuration space to contain only its minimum tick time
6273 * \param pcm PCM handle
6274 * \param params Configuration space
6275 * \param val Returned approximate minimum tick duration in us
6276 * \param dir Sub unit direction
6277 * \return 0 otherwise a negative error code
6278 *
6279 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
6280 */
6281#ifndef DOXYGEN
6282EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_tick_time_first)(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val ATTRIBUTE_UNUSED, int *dir ATTRIBUTE_UNUSED)
6283#else
6284int snd_pcm_hw_params_set_tick_time_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
6285#endif
6286{
6287	return 0;
6288}
6289
6290/**
6291 * \brief (DEPRECATED) Restrict a configuration space to contain only its maximum tick time
6292 * \param pcm PCM handle
6293 * \param params Configuration space
6294 * \param val Returned approximate maximum tick duration in us
6295 * \param dir Sub unit direction
6296 * \return 0 otherwise a negative error code
6297 *
6298 * Actual exact value is <,=,> the approximate one following dir (-1, 0, 1)
6299 */
6300#ifndef DOXYGEN
6301EXPORT_SYMBOL int INTERNAL(snd_pcm_hw_params_set_tick_time_last)(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val ATTRIBUTE_UNUSED, int *dir ATTRIBUTE_UNUSED)
6302#else
6303int snd_pcm_hw_params_set_tick_time_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
6304#endif
6305{
6306	return 0;
6307}
6308
6309/**
6310 * \brief Get the minimum transfer align value in samples
6311 * \param params Configuration space
6312 * \param val Returned minimum align value
6313 * \return 0 otherwise a negative error code if the configuration space does not contain a single value
6314 */
6315int snd_pcm_hw_params_get_min_align(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
6316{
6317	unsigned int format, channels, fb, min_align;
6318	int err;
6319
6320	err = snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_FORMAT, &format, NULL);
6321	if (err < 0)
6322		return err;
6323	err = snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_CHANNELS, &channels, NULL);
6324	if (err < 0)
6325		return err;
6326	// compute frame bits
6327	fb = snd_pcm_format_physical_width((snd_pcm_format_t)format) * channels;
6328        min_align = 1;
6329	while (fb % 8) {
6330		fb *= 2;
6331                min_align *= 2;
6332	}
6333	if (val)
6334		*val = min_align;
6335	return 0;
6336}
6337
6338#ifndef DOXYGEN
6339void snd_pcm_sw_params_current_no_lock(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
6340{
6341	params->proto = SNDRV_PCM_VERSION;
6342	params->tstamp_mode = pcm->tstamp_mode;
6343	params->tstamp_type = pcm->tstamp_type;
6344	params->period_step = pcm->period_step;
6345	params->sleep_min = 0;
6346	params->avail_min = pcm->avail_min;
6347	sw_set_period_event(params, pcm->period_event);
6348	params->xfer_align = 1;
6349	params->start_threshold = pcm->start_threshold;
6350	params->stop_threshold = pcm->stop_threshold;
6351	params->silence_threshold = pcm->silence_threshold;
6352	params->silence_size = pcm->silence_size;
6353	params->boundary = pcm->boundary;
6354}
6355#endif
6356
6357/**
6358 * \brief Return current software configuration for a PCM
6359 * \param pcm PCM handle
6360 * \param params Software configuration container
6361 * \return 0 on success otherwise a negative error code
6362 *
6363 * The function is thread-safe when built with the proper option.
6364 */
6365int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
6366{
6367	assert(pcm && params);
6368	if (CHECK_SANITY(! pcm->setup)) {
6369		SNDMSG("PCM not set up");
6370		return -EIO;
6371	}
6372	__snd_pcm_lock(pcm); /* forced lock due to pcm field changes */
6373	snd_pcm_sw_params_current_no_lock(pcm, params);
6374	__snd_pcm_unlock(pcm);
6375	return 0;
6376}
6377
6378/**
6379 * \brief Dump a software configuration
6380 * \param params Software configuration container
6381 * \param out Output handle
6382 * \return 0 on success otherwise a negative error code
6383 */
6384int snd_pcm_sw_params_dump(snd_pcm_sw_params_t *params, snd_output_t *out)
6385{
6386	snd_output_printf(out, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(params->tstamp_mode));
6387	snd_output_printf(out, "tstamp_type: %s\n", snd_pcm_tstamp_type_name(params->tstamp_type));
6388	snd_output_printf(out, "period_step: %u\n", params->period_step);
6389	snd_output_printf(out, "avail_min: %lu\n", params->avail_min);
6390	snd_output_printf(out, "start_threshold: %ld\n", params->start_threshold);
6391	snd_output_printf(out, "stop_threshold: %ld\n", params->stop_threshold);
6392	snd_output_printf(out, "silence_threshold: %lu\n", params->silence_threshold);
6393	snd_output_printf(out, "silence_size: %lu\n", params->silence_size);
6394	snd_output_printf(out, "boundary: %lu\n", params->boundary);
6395	return 0;
6396}
6397
6398/**
6399 * \brief get size of #snd_pcm_sw_params_t
6400 * \return size in bytes
6401 */
6402size_t snd_pcm_sw_params_sizeof()
6403{
6404	return sizeof(snd_pcm_sw_params_t);
6405}
6406
6407/**
6408 * \brief allocate an invalid #snd_pcm_sw_params_t using standard malloc
6409 * \param ptr returned pointer
6410 * \return 0 on success otherwise negative error code
6411 */
6412int snd_pcm_sw_params_malloc(snd_pcm_sw_params_t **ptr)
6413{
6414	assert(ptr);
6415	*ptr = calloc(1, sizeof(snd_pcm_sw_params_t));
6416	if (!*ptr)
6417		return -ENOMEM;
6418	return 0;
6419}
6420
6421/**
6422 * \brief frees a previously allocated #snd_pcm_sw_params_t
6423 * \param obj pointer to object to free
6424 */
6425void snd_pcm_sw_params_free(snd_pcm_sw_params_t *obj)
6426{
6427	free(obj);
6428}
6429
6430/**
6431 * \brief copy one #snd_pcm_sw_params_t to another
6432 * \param dst pointer to destination
6433 * \param src pointer to source
6434 */
6435void snd_pcm_sw_params_copy(snd_pcm_sw_params_t *dst, const snd_pcm_sw_params_t *src)
6436{
6437	assert(dst && src);
6438	*dst = *src;
6439}
6440
6441/**
6442 * \brief Get boundary for ring pointers from a software configuration container
6443 * \param params Software configuration container
6444 * \param val Returned boundary in frames
6445 * \return 0 otherwise a negative error code
6446 */
6447int snd_pcm_sw_params_get_boundary(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6448{
6449	assert(params);
6450	*val = params->boundary;
6451	return 0;
6452}
6453
6454/**
6455 * \brief (DEPRECATED) Set start mode inside a software configuration container
6456 * \param pcm PCM handle
6457 * \param params Software configuration container
6458 * \param val Start mode
6459 * \return 0 otherwise a negative error code
6460 */
6461int snd_pcm_sw_params_set_start_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_start_t val)
6462{
6463	assert(pcm && params);
6464	switch (val) {
6465	case SND_PCM_START_DATA:
6466		params->start_threshold = 1;
6467		break;
6468	case SND_PCM_START_EXPLICIT:
6469		params->start_threshold = pcm->boundary;
6470		break;
6471	default:
6472		SNDMSG("invalid start mode value %d", val);
6473		return -EINVAL;
6474	}
6475	return 0;
6476}
6477
6478#ifndef DOC_HIDDEN
6479link_warning(snd_pcm_sw_params_set_start_mode, "Warning: start_mode is deprecated, consider to use start_threshold");
6480#endif
6481
6482/**
6483 * \brief (DEPRECATED) Get start mode from a software configuration container
6484 * \param params Software configuration container
6485 * \return start mode
6486 */
6487snd_pcm_start_t snd_pcm_sw_params_get_start_mode(const snd_pcm_sw_params_t *params)
6488{
6489	assert(params);
6490	/* FIXME: Ugly */
6491	return params->start_threshold > 1024 * 1024 ? SND_PCM_START_EXPLICIT : SND_PCM_START_DATA;
6492}
6493
6494#ifndef DOC_HIDDEN
6495link_warning(snd_pcm_sw_params_get_start_mode, "Warning: start_mode is deprecated, consider to use start_threshold");
6496#endif
6497
6498/**
6499 * \brief (DEPRECATED) Set xrun mode inside a software configuration container
6500 * \param pcm PCM handle
6501 * \param params Software configuration container
6502 * \param val Xrun mode
6503 * \return 0 otherwise a negative error code
6504 */
6505#ifndef DOXYGEN
6506int snd_pcm_sw_params_set_xrun_mode(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_xrun_t val)
6507#else
6508int snd_pcm_sw_params_set_xrun_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_xrun_t val)
6509#endif
6510{
6511	assert(pcm && params);
6512	switch (val) {
6513	case SND_PCM_XRUN_STOP:
6514		params->stop_threshold = pcm->buffer_size;
6515		break;
6516	case SND_PCM_XRUN_NONE:
6517		params->stop_threshold = pcm->boundary;
6518		break;
6519	default:
6520		SNDMSG("invalid xrun mode value %d", val);
6521		return -EINVAL;
6522	}
6523	return 0;
6524}
6525
6526#ifndef DOC_HIDDEN
6527link_warning(snd_pcm_sw_params_set_xrun_mode, "Warning: xrun_mode is deprecated, consider to use stop_threshold");
6528#endif
6529
6530/**
6531 * \brief (DEPRECATED) Get xrun mode from a software configuration container
6532 * \param params Software configuration container
6533 * \return xrun mode
6534 */
6535snd_pcm_xrun_t snd_pcm_sw_params_get_xrun_mode(const snd_pcm_sw_params_t *params)
6536{
6537	assert(params);
6538	/* FIXME: Ugly */
6539	return params->stop_threshold > 1024 * 1024 ? SND_PCM_XRUN_NONE : SND_PCM_XRUN_STOP;
6540}
6541
6542#ifndef DOC_HIDDEN
6543link_warning(snd_pcm_sw_params_get_xrun_mode, "Warning: xrun_mode is deprecated, consider to use stop_threshold");
6544#endif
6545
6546/**
6547 * \brief Set timestamp mode inside a software configuration container
6548 * \param pcm PCM handle
6549 * \param params Software configuration container
6550 * \param val Timestamp mode
6551 * \return 0 otherwise a negative error code
6552 */
6553#ifndef DOXYGEN
6554int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_tstamp_t val)
6555#else
6556int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_t val)
6557#endif
6558{
6559	assert(pcm && params);
6560	if (CHECK_SANITY(val > SND_PCM_TSTAMP_LAST)) {
6561		SNDMSG("invalid tstamp_mode value %d", val);
6562		return -EINVAL;
6563	}
6564	params->tstamp_mode = val;
6565	return 0;
6566}
6567
6568/**
6569 * \brief Get timestamp mode from a software configuration container
6570 * \param params Software configuration container
6571 * \param val Returned timestamp
6572 * \return 0 otherwise a negative error code
6573 */
6574#ifndef DOXYGEN
6575EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_tstamp_mode)(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_t *val)
6576#else
6577int snd_pcm_sw_params_get_tstamp_mode(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_t *val)
6578#endif
6579{
6580	assert(params && val);
6581	*val = params->tstamp_mode;
6582	return 0;
6583}
6584
6585/**
6586 * \brief Set timestamp type inside a software configuration container
6587 * \param pcm PCM handle
6588 * \param params Software configuration container
6589 * \param val Timestamp type
6590 * \return 0 otherwise a negative error code
6591 */
6592int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t val)
6593{
6594	assert(pcm && params);
6595	if (CHECK_SANITY(val > SND_PCM_TSTAMP_TYPE_LAST)) {
6596		SNDMSG("invalid tstamp_type value %d", val);
6597		return -EINVAL;
6598	}
6599	params->tstamp_type = val;
6600	return 0;
6601}
6602
6603/**
6604 * \brief Get timestamp type from a software configuration container
6605 * \param params Software configuration container
6606 * \param val Returned timestamp type
6607 * \return 0 otherwise a negative error code
6608 */
6609int snd_pcm_sw_params_get_tstamp_type(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t *val)
6610{
6611	assert(params && val);
6612	*val = params->tstamp_type;
6613	return 0;
6614}
6615
6616/**
6617 * \brief (DEPRECATED) Set minimum number of ticks to sleep inside a software configuration container
6618 * \param pcm PCM handle
6619 * \param params Software configuration container
6620 * \param val Minimum ticks to sleep or 0 to disable the use of tick timer
6621 * \return 0 otherwise a negative error code
6622 */
6623#ifndef DOXYGEN
6624int snd_pcm_sw_params_set_sleep_min(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params ATTRIBUTE_UNUSED, unsigned int val ATTRIBUTE_UNUSED)
6625#else
6626int snd_pcm_sw_params_set_sleep_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, unsigned int val)
6627#endif
6628{
6629	return 0;
6630}
6631
6632/**
6633 * \brief (DEPRECATED) Get minimum numbers of ticks to sleep from a software configuration container
6634 * \param params Software configuration container
6635 * \param val returned minimum number of ticks to sleep or 0 if tick timer is disabled
6636 * \return 0 otherwise a negative error code
6637 */
6638#ifndef DOXYGEN
6639EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_sleep_min)(const snd_pcm_sw_params_t *params ATTRIBUTE_UNUSED, unsigned int *val)
6640#else
6641int snd_pcm_sw_params_get_sleep_min(const snd_pcm_sw_params_t *params, unsigned int *val)
6642#endif
6643{
6644	*val = 0;
6645	return 0;
6646}
6647
6648/**
6649 * \brief Set avail min inside a software configuration container
6650 * \param pcm PCM handle
6651 * \param params Software configuration container
6652 * \param val Minimum avail frames to consider PCM ready
6653 * \return 0 otherwise a negative error code
6654 *
6655 * Note: This is similar to setting an OSS wakeup point.  The valid
6656 * values for 'val' are determined by the specific hardware.  Most PC
6657 * sound cards can only accept power of 2 frame counts (i.e. 512,
6658 * 1024, 2048).  You cannot use this as a high resolution timer - it
6659 * is limited to how often the sound card hardware raises an
6660 * interrupt.
6661 */
6662#ifndef DOXYGEN
6663EXPORT_SYMBOL int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6664#else
6665int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6666#endif
6667{
6668	assert(pcm && params);
6669	/* Fix avail_min if it's below period size.  The period_size
6670	 * defines the minimal wake-up timing accuracy, so it doesn't
6671	 * make sense to set below that.
6672	 */
6673	if (val < pcm->period_size)
6674		val = pcm->period_size;
6675	params->avail_min = val;
6676	return 0;
6677}
6678
6679/**
6680 * \brief Get avail min from a software configuration container
6681 * \param params Software configuration container
6682 * \param val returned minimum available frames to consider PCM ready
6683 * \return 0 otherwise a negative error code
6684 *
6685 * This is a threshold value when the PCM stream is considered as ready for
6686 * another read/write operation or poll event.
6687 */
6688#ifndef DOXYGEN
6689EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_avail_min)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6690#else
6691int snd_pcm_sw_params_get_avail_min(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6692#endif
6693{
6694	assert(params && val);
6695	*val = params->avail_min;
6696	return 0;
6697}
6698
6699/**
6700 * \brief Set period event inside a software configuration container
6701 * \param pcm PCM handle
6702 * \param params Software configuration container
6703 * \param val 0 = disable period event, 1 = enable period event
6704 * \return 0 otherwise a negative error code
6705 *
6706 * An poll (select) wakeup event is raised if enabled.
6707 */
6708int snd_pcm_sw_params_set_period_event(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, int val)
6709{
6710	assert(pcm && params);
6711	sw_set_period_event(params, val);
6712	return 0;
6713}
6714
6715/**
6716 * \brief Get period event from a software configuration container
6717 * \param params Software configuration container
6718 * \param val returned period event state
6719 * \return 0 otherwise a negative error code
6720 */
6721int snd_pcm_sw_params_get_period_event(const snd_pcm_sw_params_t *params, int *val)
6722{
6723	assert(params && val);
6724	*val = sw_get_period_event(params);
6725	return 0;
6726}
6727
6728/**
6729 * \brief (DEPRECATED) Set xfer align inside a software configuration container
6730 * \param pcm PCM handle
6731 * \param params Software configuration container
6732 * \param val Chunk size (frames are attempted to be transferred in chunks)
6733 * \return 0 otherwise a negative error code
6734 */
6735#ifndef DOXYGEN
6736EXPORT_SYMBOL int snd_pcm_sw_params_set_xfer_align(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params ATTRIBUTE_UNUSED, snd_pcm_uframes_t val ATTRIBUTE_UNUSED)
6737#else
6738int snd_pcm_sw_params_set_xfer_align(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6739#endif
6740{
6741	return 0;
6742}
6743
6744/**
6745 * \brief (DEPRECATED) Get xfer align from a software configuration container
6746 * \param params Software configuration container
6747 * \param val returned chunk size (frames are attempted to be transferred in chunks)
6748 * \return 0 otherwise a negative error code
6749 */
6750#ifndef DOXYGEN
6751EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_xfer_align)(const snd_pcm_sw_params_t *params ATTRIBUTE_UNUSED, snd_pcm_uframes_t *val)
6752#else
6753int snd_pcm_sw_params_get_xfer_align(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6754#endif
6755{
6756	*val = 1;
6757	return 0;
6758}
6759
6760/**
6761 * \brief Set start threshold inside a software configuration container
6762 * \param pcm PCM handle
6763 * \param params Software configuration container
6764 * \param val Start threshold in frames
6765 * \return 0 otherwise a negative error code
6766 *
6767 * PCM is automatically started when playback frames available to PCM
6768 * are >= threshold or when requested capture frames are >= threshold
6769 */
6770#ifndef DOXYGEN
6771EXPORT_SYMBOL int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6772#else
6773int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6774#endif
6775{
6776	assert(pcm && params);
6777	params->start_threshold = val;
6778	return 0;
6779}
6780
6781/**
6782 * \brief Get start threshold from a software configuration container
6783 * \param params Software configuration container
6784 * \param val Returned start threshold in frames
6785 * \return 0 otherwise a negative error code
6786 *
6787 * PCM is automatically started when playback frames available to PCM
6788 * are >= threshold or when requested capture frames are >= threshold
6789 */
6790#ifndef DOXYGEN
6791EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_start_threshold)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6792#else
6793int snd_pcm_sw_params_get_start_threshold(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6794#endif
6795{
6796	assert(params);
6797	*val = params->start_threshold;
6798	return 0;
6799}
6800
6801
6802/**
6803 * \brief Set stop threshold inside a software configuration container
6804 * \param pcm PCM handle
6805 * \param params Software configuration container
6806 * \param val Stop threshold in frames
6807 * \return 0 otherwise a negative error code
6808 *
6809 * PCM is automatically stopped in #SND_PCM_STATE_XRUN state when available
6810 * frames is >= threshold. If the stop threshold is equal to boundary (also
6811 * software parameter - sw_param) then automatic stop will be disabled
6812 * (thus device will do the endless loop in the ring buffer).
6813 */
6814#ifndef DOXYGEN
6815EXPORT_SYMBOL int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6816#else
6817int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6818#endif
6819{
6820	assert(pcm && params);
6821	params->stop_threshold = val;
6822	return 0;
6823}
6824
6825/**
6826 * \brief Get stop threshold from a software configuration container
6827 * \param params Software configuration container
6828 * \param val Returned stop threshold in frames
6829 * \return 0 otherwise a negative error code
6830 *
6831 * PCM is automatically stopped in #SND_PCM_STATE_XRUN state when available
6832 * frames is >= threshold. If the stop threshold is equal to boundary (also
6833 * software parameter - sw_param) then automatic stop will be disabled
6834 * (thus device will do the endless loop in the ring buffer).
6835 */
6836#ifndef DOXYGEN
6837EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_stop_threshold)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6838#else
6839int snd_pcm_sw_params_get_stop_threshold(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6840#endif
6841{
6842	assert(params);
6843	*val = params->stop_threshold;
6844	return 0;
6845}
6846
6847
6848/**
6849 * \brief Set silence threshold inside a software configuration container
6850 * \param pcm PCM handle
6851 * \param params Software configuration container
6852 * \param val Silence threshold in frames
6853 * \return 0 otherwise a negative error code
6854 *
6855 * A portion of playback buffer is overwritten with silence (see
6856 * #snd_pcm_sw_params_set_silence_size) when playback underrun is nearer
6857 * than silence threshold.
6858 */
6859#ifndef DOXYGEN
6860EXPORT_SYMBOL int snd_pcm_sw_params_set_silence_threshold(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6861#else
6862int snd_pcm_sw_params_set_silence_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6863#endif
6864{
6865	assert(pcm && params);
6866	if (CHECK_SANITY(val >= pcm->buffer_size)) {
6867		SNDMSG("invalid silent_threshold value %ld (buffer_size = %ld)",
6868		       val, pcm->buffer_size);
6869		return -EINVAL;
6870	}
6871	params->silence_threshold = val;
6872	return 0;
6873}
6874
6875/**
6876 * \brief Get silence threshold from a software configuration container
6877 * \param params Software configuration container
6878 * \param val Returned silence threshold in frames
6879 * \return 0 otherwise a negative error value
6880 *
6881 * A portion of playback buffer is overwritten with silence (see
6882 * #snd_pcm_sw_params_set_silence_size) when playback underrun is nearer
6883 * than silence threshold.
6884 */
6885#ifndef DOXYGEN
6886EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_silence_threshold)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6887#else
6888int snd_pcm_sw_params_get_silence_threshold(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6889#endif
6890{
6891	assert(params && val);
6892	*val = params->silence_threshold;
6893	return 0;
6894}
6895
6896
6897/**
6898 * \brief Set silence size inside a software configuration container
6899 * \param pcm PCM handle
6900 * \param params Software configuration container
6901 * \param val Silence size in frames (0 for disabled)
6902 * \return 0 otherwise a negative error code
6903 *
6904 * A portion of playback buffer is overwritten with silence when playback
6905 * underrun is nearer than silence threshold (see
6906 * #snd_pcm_sw_params_set_silence_threshold)
6907 *
6908 * When drain silence (see #snd_pcm_hw_params_get_drain_silence) is disabled,
6909 * this will also apply for draining, i.e. silence is written also when the
6910 * drain end is nearer than the silence threshold.
6911 *
6912 * The special case is when silence size value is equal or greater than
6913 * boundary. The unused portion of the ring buffer (initial written samples
6914 * are untouched) is filled with silence at start. Later, only just processed
6915 * sample area is filled with silence. Note: silence_threshold must be set to zero.
6916 */
6917#ifndef DOXYGEN
6918EXPORT_SYMBOL int snd_pcm_sw_params_set_silence_size(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6919#else
6920int snd_pcm_sw_params_set_silence_size(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val)
6921#endif
6922{
6923	assert(pcm && params);
6924	if (CHECK_SANITY(val < pcm->boundary && val > pcm->buffer_size)) {
6925		SNDMSG("invalid silence_size %ld (boundary %ld, buffer_size %ld)",
6926		       val, pcm->boundary, pcm->buffer_size);
6927		return -EINVAL;
6928	}
6929	params->silence_size = val;
6930	return 0;
6931}
6932
6933/**
6934 * \brief Get silence size from a software configuration container
6935 * \param params Software configuration container
6936 * \param val Returned silence size in frames (0 for disabled)
6937 * \return 0 otherwise a negative error code
6938 *
6939 * A portion of playback buffer is overwritten with silence when playback
6940 * underrun is nearer than silence threshold (see
6941 * #snd_pcm_sw_params_set_silence_threshold)
6942 */
6943#ifndef DOXYGEN
6944EXPORT_SYMBOL int INTERNAL(snd_pcm_sw_params_get_silence_size)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6945#else
6946int snd_pcm_sw_params_get_silence_size(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val)
6947#endif
6948{
6949	assert(params);
6950	*val = params->silence_size;
6951	return 0;
6952}
6953
6954
6955/**
6956 * \brief get size of #snd_pcm_status_t
6957 * \return size in bytes
6958 */
6959size_t snd_pcm_status_sizeof()
6960{
6961	return sizeof(snd_pcm_status_t);
6962}
6963
6964/**
6965 * \brief allocate an invalid #snd_pcm_status_t using standard malloc
6966 * \param ptr returned pointer
6967 * \return 0 on success otherwise negative error code
6968 */
6969int snd_pcm_status_malloc(snd_pcm_status_t **ptr)
6970{
6971	assert(ptr);
6972	*ptr = calloc(1, sizeof(snd_pcm_status_t));
6973	if (!*ptr)
6974		return -ENOMEM;
6975	return 0;
6976}
6977
6978/**
6979 * \brief frees a previously allocated #snd_pcm_status_t
6980 * \param obj pointer to object to free
6981 */
6982void snd_pcm_status_free(snd_pcm_status_t *obj)
6983{
6984	free(obj);
6985}
6986
6987/**
6988 * \brief copy one #snd_pcm_status_t to another
6989 * \param dst pointer to destination
6990 * \param src pointer to source
6991 */
6992void snd_pcm_status_copy(snd_pcm_status_t *dst, const snd_pcm_status_t *src)
6993{
6994	assert(dst && src);
6995	*dst = *src;
6996}
6997
6998/**
6999 * \brief Get state from a PCM status container (see #snd_pcm_state)
7000 * \param obj #snd_pcm_status_t pointer
7001 * \return PCM state
7002 */
7003snd_pcm_state_t snd_pcm_status_get_state(const snd_pcm_status_t *obj)
7004{
7005	assert(obj);
7006	return obj->state;
7007}
7008
7009/**
7010 * \brief Get trigger timestamp from a PCM status container
7011 * \param obj #snd_pcm_status_t pointer
7012 * \param ptr Pointer to returned timestamp
7013 *
7014 * Trigger means a PCM state transition (from stopped to running or
7015 * versa vice). It applies also to pause and suspend. In other words,
7016 * timestamp contains time when stream started or when it was stopped.
7017 */
7018void snd_pcm_status_get_trigger_tstamp(const snd_pcm_status_t *obj, snd_timestamp_t *ptr)
7019{
7020	assert(obj && ptr);
7021	ptr->tv_sec = obj->trigger_tstamp.tv_sec;
7022	ptr->tv_usec = obj->trigger_tstamp.tv_nsec / 1000L;
7023}
7024
7025/**
7026 * \brief Get trigger hi-res timestamp from a PCM status container
7027 * \param obj #snd_pcm_status_t pointer
7028 * \param ptr Pointer to returned timestamp
7029 *
7030 * Trigger means a PCM state transition (from stopped to running or
7031 * versa vice). It applies also to pause and suspend. In other words,
7032 * timestamp contains time when stream started or when it was stopped.
7033 */
7034#ifndef DOXYGEN
7035EXPORT_SYMBOL void INTERNAL(snd_pcm_status_get_trigger_htstamp)(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
7036#else
7037void snd_pcm_status_get_trigger_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
7038#endif
7039{
7040	assert(obj && ptr);
7041	*ptr = obj->trigger_tstamp;
7042}
7043use_default_symbol_version(__snd_pcm_status_get_trigger_htstamp, snd_pcm_status_get_trigger_htstamp, ALSA_0.9.0rc8);
7044
7045/**
7046 * \brief Get "now" timestamp from a PCM status container
7047 * \param obj #snd_pcm_status_t pointer
7048 * \param ptr Pointer to returned timestamp
7049 */
7050void snd_pcm_status_get_tstamp(const snd_pcm_status_t *obj, snd_timestamp_t *ptr)
7051{
7052	assert(obj && ptr);
7053	ptr->tv_sec = obj->tstamp.tv_sec;
7054	ptr->tv_usec = obj->tstamp.tv_nsec / 1000L;
7055}
7056
7057/**
7058 * \brief Get "now" hi-res timestamp from a PCM status container
7059 * \param obj pointer to #snd_pcm_status_t
7060 * \param ptr Pointer to returned timestamp
7061 */
7062#ifndef DOXYGEN
7063EXPORT_SYMBOL void INTERNAL(snd_pcm_status_get_htstamp)(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
7064#else
7065void snd_pcm_status_get_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
7066#endif
7067{
7068	assert(obj && ptr);
7069	*ptr = obj->tstamp;
7070}
7071use_default_symbol_version(__snd_pcm_status_get_htstamp, snd_pcm_status_get_htstamp, ALSA_0.9.0rc8);
7072
7073/**
7074 * \brief Get "now" hi-res audio timestamp from a PCM status container
7075 * \param obj pointer to #snd_pcm_status_t
7076 * \param ptr Pointer to returned timestamp
7077 */
7078void snd_pcm_status_get_audio_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
7079{
7080	assert(obj && ptr);
7081	*ptr = obj->audio_tstamp;
7082}
7083
7084/**
7085 * \brief Get "now" hi-res driver timestamp from a PCM status container. Defines when the status
7086 * was generated by driver, may differ from normal timestamp.
7087 * \param obj pointer to #snd_pcm_status_t
7088 * \param ptr Pointer to returned timestamp
7089 */
7090void snd_pcm_status_get_driver_htstamp(const snd_pcm_status_t *obj, snd_htimestamp_t *ptr)
7091{
7092	assert(obj && ptr);
7093	*ptr = obj->driver_tstamp;
7094}
7095
7096/**
7097 * \brief Get audio_tstamp_report from a PCM status container
7098 * \param obj pointer to #snd_pcm_status_t
7099 * \param audio_tstamp_report Pointer to returned report
7100 */
7101void snd_pcm_status_get_audio_htstamp_report(const snd_pcm_status_t *obj,
7102					     snd_pcm_audio_tstamp_report_t *audio_tstamp_report)
7103{
7104	assert(obj && audio_tstamp_report);
7105	snd_pcm_unpack_audio_tstamp_report(obj->audio_tstamp_data,
7106					obj->audio_tstamp_accuracy,
7107					audio_tstamp_report);
7108}
7109
7110/**
7111 * \brief set audio_tstamp_config from a PCM status container
7112 * \param obj pointer to #snd_pcm_status_t
7113 * \param audio_tstamp_config Pointer to config (valid fields are type_requested and report_delay)
7114 */
7115void snd_pcm_status_set_audio_htstamp_config(snd_pcm_status_t *obj,
7116					     snd_pcm_audio_tstamp_config_t *audio_tstamp_config)
7117{
7118	assert(obj && audio_tstamp_config);
7119	snd_pcm_pack_audio_tstamp_config(&obj->audio_tstamp_data, audio_tstamp_config);
7120}
7121
7122/**
7123 * \brief Get delay from a PCM status container (see #snd_pcm_delay)
7124 * \return Delay in frames
7125 *
7126 * Delay is distance between current application frame position and
7127 * sound frame position.
7128 * It's positive and less than buffer size in normal situation,
7129 * negative on playback underrun and greater than buffer size on
7130 * capture overrun.
7131 */
7132snd_pcm_sframes_t snd_pcm_status_get_delay(const snd_pcm_status_t *obj)
7133{
7134	assert(obj);
7135	return obj->delay;
7136}
7137
7138/**
7139 * \brief Get number of frames available from a PCM status container (see #snd_pcm_avail_update)
7140 * \return Number of frames ready to be read/written
7141 */
7142snd_pcm_uframes_t snd_pcm_status_get_avail(const snd_pcm_status_t *obj)
7143{
7144	assert(obj);
7145	return obj->avail;
7146}
7147
7148/**
7149 * \brief Get maximum number of frames available from a PCM status container after last #snd_pcm_status call
7150 * \return Maximum number of frames ready to be read/written
7151 *
7152 * This value returns the peak for the available frames between #snd_pcm_status calls.
7153 */
7154snd_pcm_uframes_t snd_pcm_status_get_avail_max(const snd_pcm_status_t *obj)
7155{
7156	assert(obj);
7157	return obj->avail_max;
7158}
7159
7160/**
7161 * \brief Get count of ADC overrange detections since last call
7162 * \return Count of ADC overrange detections
7163 */
7164snd_pcm_uframes_t snd_pcm_status_get_overrange(const snd_pcm_status_t *obj)
7165{
7166	assert(obj);
7167	return obj->overrange;
7168}
7169
7170/**
7171 * \brief get size of #snd_pcm_info_t
7172 * \return size in bytes
7173 */
7174size_t snd_pcm_info_sizeof()
7175{
7176	return sizeof(snd_pcm_info_t);
7177}
7178
7179/**
7180 * \brief allocate an invalid #snd_pcm_info_t using standard malloc
7181 * \param ptr returned pointer
7182 * \return 0 on success otherwise negative error code
7183 */
7184int snd_pcm_info_malloc(snd_pcm_info_t **ptr)
7185{
7186	assert(ptr);
7187	*ptr = calloc(1, sizeof(snd_pcm_info_t));
7188	if (!*ptr)
7189		return -ENOMEM;
7190	return 0;
7191}
7192
7193/**
7194 * \brief frees a previously allocated #snd_pcm_info_t
7195 * \param obj pointer to object to free
7196 */
7197void snd_pcm_info_free(snd_pcm_info_t *obj)
7198{
7199	free(obj);
7200}
7201
7202/**
7203 * \brief copy one #snd_pcm_info_t to another
7204 * \param dst pointer to destination
7205 * \param src pointer to source
7206 */
7207void snd_pcm_info_copy(snd_pcm_info_t *dst, const snd_pcm_info_t *src)
7208{
7209	assert(dst && src);
7210	*dst = *src;
7211}
7212
7213/**
7214 * \brief Get device from a PCM info container
7215 * \param obj PCM info container
7216 * \return device number
7217 */
7218unsigned int snd_pcm_info_get_device(const snd_pcm_info_t *obj)
7219{
7220	assert(obj);
7221	return obj->device;
7222}
7223
7224/**
7225 * \brief Get subdevice from a PCM info container
7226 * \param obj PCM info container
7227 * \return subdevice number
7228 */
7229unsigned int snd_pcm_info_get_subdevice(const snd_pcm_info_t *obj)
7230{
7231	assert(obj);
7232	return obj->subdevice;
7233}
7234
7235/**
7236 * \brief Get stream (direction) from a PCM info container
7237 * \param obj PCM info container
7238 * \return stream
7239 */
7240snd_pcm_stream_t snd_pcm_info_get_stream(const snd_pcm_info_t *obj)
7241{
7242	assert(obj);
7243	return obj->stream;
7244}
7245
7246/**
7247 * \brief Get card from a PCM info container
7248 * \param obj PCM info container
7249 * \return card number otherwise a negative error code if not associable to a card
7250 */
7251int snd_pcm_info_get_card(const snd_pcm_info_t *obj)
7252{
7253	assert(obj);
7254	return obj->card;
7255}
7256
7257/**
7258 * \brief Get id from a PCM info container
7259 * \param obj PCM info container
7260 * \return short id of PCM
7261 */
7262const char *snd_pcm_info_get_id(const snd_pcm_info_t *obj)
7263{
7264	assert(obj);
7265	return (const char *)obj->id;
7266}
7267
7268/**
7269 * \brief Get name from a PCM info container
7270 * \param obj PCM info container
7271 * \return name of PCM
7272 */
7273const char *snd_pcm_info_get_name(const snd_pcm_info_t *obj)
7274{
7275	assert(obj);
7276	return (const char *)obj->name;
7277}
7278
7279/**
7280 * \brief Get subdevice name from a PCM info container
7281 * \param obj PCM info container
7282 * \return name of used PCM subdevice
7283 */
7284const char *snd_pcm_info_get_subdevice_name(const snd_pcm_info_t *obj)
7285{
7286	assert(obj);
7287	return (const char *)obj->subname;
7288}
7289
7290/**
7291 * \brief Get class from a PCM info container
7292 * \param obj PCM info container
7293 * \return class of PCM
7294 */
7295snd_pcm_class_t snd_pcm_info_get_class(const snd_pcm_info_t *obj)
7296{
7297	assert(obj);
7298	return obj->dev_class;
7299}
7300
7301/**
7302 * \brief Get subclass from a PCM info container
7303 * \param obj PCM info container
7304 * \return subclass of PCM
7305 */
7306snd_pcm_subclass_t snd_pcm_info_get_subclass(const snd_pcm_info_t *obj)
7307{
7308	assert(obj);
7309	return obj->dev_subclass;
7310}
7311
7312/**
7313 * \brief Get subdevices count from a PCM info container
7314 * \param obj PCM info container
7315 * \return subdevices total count of PCM
7316 */
7317unsigned int snd_pcm_info_get_subdevices_count(const snd_pcm_info_t *obj)
7318{
7319	assert(obj);
7320	return obj->subdevices_count;
7321}
7322
7323/**
7324 * \brief Get available subdevices count from a PCM info container
7325 * \param obj PCM info container
7326 * \return available subdevices count of PCM
7327 */
7328unsigned int snd_pcm_info_get_subdevices_avail(const snd_pcm_info_t *obj)
7329{
7330	assert(obj);
7331	return obj->subdevices_avail;
7332}
7333
7334/**
7335 * \brief Get hardware synchronization ID from a PCM info container
7336 * \param obj PCM info container
7337 * \return hardware synchronization ID
7338 */
7339snd_pcm_sync_id_t snd_pcm_info_get_sync(const snd_pcm_info_t *obj)
7340{
7341	snd_pcm_sync_id_t res;
7342	assert(obj);
7343	memcpy(&res, &obj->sync, sizeof(res));
7344	return res;
7345}
7346
7347/**
7348 * \brief Set wanted device inside a PCM info container (see #snd_ctl_pcm_info)
7349 * \param obj PCM info container
7350 * \param val Device number
7351 */
7352void snd_pcm_info_set_device(snd_pcm_info_t *obj, unsigned int val)
7353{
7354	assert(obj);
7355	obj->device = val;
7356}
7357
7358/**
7359 * \brief Set wanted subdevice inside a PCM info container (see #snd_ctl_pcm_info)
7360 * \param obj PCM info container
7361 * \param val Subdevice number
7362 */
7363void snd_pcm_info_set_subdevice(snd_pcm_info_t *obj, unsigned int val)
7364{
7365	assert(obj);
7366	obj->subdevice = val;
7367}
7368
7369/**
7370 * \brief Set wanted stream inside a PCM info container (see #snd_ctl_pcm_info)
7371 * \param obj PCM info container
7372 * \param val Stream
7373 */
7374void snd_pcm_info_set_stream(snd_pcm_info_t *obj, snd_pcm_stream_t val)
7375{
7376	assert(obj);
7377	obj->stream = val;
7378}
7379
7380/**
7381 * \brief Application request to access a portion of direct (mmap) area
7382 * \param pcm PCM handle
7383 * \param areas Returned mmap channel areas
7384 * \param offset Returned mmap area offset in area steps (== frames)
7385 * \param frames mmap area portion size in frames (wanted on entry, contiguous available on exit)
7386 * \return 0 on success otherwise a negative error code
7387 *
7388 * It is necessary to call the snd_pcm_avail_update() function directly before
7389 * this call. Otherwise, this function can return a wrong count of available frames.
7390 *
7391 * The function should be called before a sample-direct area can be accessed.
7392 * The resulting size parameter is always less or equal to the input count of frames
7393 * and can be zero, if no frames can be processed (the ring buffer is full).
7394 *
7395 * See the snd_pcm_mmap_commit() function to finish the frame processing in
7396 * the direct areas.
7397 *
7398 * The function is thread-safe when built with the proper option.
7399 */
7400int snd_pcm_mmap_begin(snd_pcm_t *pcm,
7401		       const snd_pcm_channel_area_t **areas,
7402		       snd_pcm_uframes_t *offset,
7403		       snd_pcm_uframes_t *frames)
7404{
7405	int err;
7406
7407	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
7408	if (err < 0)
7409		return err;
7410	snd_pcm_lock(pcm->fast_op_arg);
7411	err = __snd_pcm_mmap_begin(pcm, areas, offset, frames);
7412	snd_pcm_unlock(pcm->fast_op_arg);
7413	return err;
7414}
7415
7416#ifndef DOC_HIDDEN
7417int __snd_pcm_mmap_begin_generic(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
7418				 snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
7419{
7420	snd_pcm_uframes_t cont;
7421	snd_pcm_uframes_t f;
7422	snd_pcm_uframes_t avail;
7423	const snd_pcm_channel_area_t *xareas;
7424
7425	assert(pcm && areas && offset && frames);
7426
7427	/* fallback for plugins that do not specify new callback */
7428	xareas = snd_pcm_mmap_areas(pcm);
7429	if (xareas == NULL)
7430		return -EBADFD;
7431	*areas = xareas;
7432	*offset = *pcm->appl.ptr % pcm->buffer_size;
7433	avail = snd_pcm_mmap_avail(pcm);
7434	if (avail > pcm->buffer_size)
7435		avail = pcm->buffer_size;
7436	cont = pcm->buffer_size - *offset;
7437	f = *frames;
7438	if (f > avail)
7439		f = avail;
7440	if (f > cont)
7441		f = cont;
7442	*frames = f;
7443	return 0;
7444}
7445
7446/* locked version */
7447int __snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas,
7448			 snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames)
7449{
7450	assert(pcm && areas && offset && frames);
7451
7452	if (pcm->fast_ops->mmap_begin)
7453		return pcm->fast_ops->mmap_begin(pcm->fast_op_arg, areas, offset, frames);
7454
7455	return __snd_pcm_mmap_begin_generic(pcm, areas, offset, frames);
7456}
7457#endif
7458
7459/**
7460 * \brief Application has completed the access to area requested with #snd_pcm_mmap_begin
7461 * \param pcm PCM handle
7462 * \param offset area offset in area steps (== frames)
7463 * \param frames area portion size in frames
7464 * \return count of transferred frames otherwise a negative error code
7465 *
7466 * You should pass this function the offset value that
7467 * snd_pcm_mmap_begin() returned. The frames parameter should hold the
7468 * number of frames you have written or read to/from the audio
7469 * buffer. The frames parameter must never exceed the contiguous frames
7470 * count that snd_pcm_mmap_begin() returned. Each call to snd_pcm_mmap_begin()
7471 * must be followed by a call to snd_pcm_mmap_commit().
7472 *
7473 * Example:
7474\code
7475  double phase = 0;
7476  const snd_pcm_area_t *areas;
7477  snd_pcm_sframes_t avail, size, commitres;
7478  snd_pcm_uframes_t offset, frames;
7479  int err;
7480
7481  avail = snd_pcm_avail_update(pcm);
7482  if (avail < 0)
7483    error(avail);
7484  // at this point, we can transfer at least 'avail' frames
7485
7486  // we want to process frames in chunks (period_size)
7487  if (avail < period_size)
7488    goto _skip;
7489  size = period_size;
7490  // it is possible that contiguous areas are smaller, thus we use a loop
7491  while (size > 0) {
7492    frames = size;
7493
7494    err = snd_pcm_mmap_begin(pcm_handle, &areas, &offset, &frames);
7495    if (err < 0)
7496      error(err);
7497    // this function fills the areas from offset with count of frames
7498    generate_sine(areas, offset, frames, &phase);
7499    commitres = snd_pcm_mmap_commit(pcm_handle, offset, frames);
7500    if (commitres < 0 || commitres != frames)
7501      error(commitres >= 0 ? -EPIPE : commitres);
7502
7503    size -= frames;
7504  }
7505 _skip:
7506\endcode
7507 *
7508 * Look to the \link example_test_pcm Sine-wave generator \endlink example
7509 * for more details about the generate_sine function.
7510 *
7511 * The function is thread-safe when built with the proper option.
7512 */
7513snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm,
7514				      snd_pcm_uframes_t offset,
7515				      snd_pcm_uframes_t frames)
7516{
7517	snd_pcm_sframes_t result;
7518	int err;
7519
7520	err = bad_pcm_state(pcm, P_STATE_RUNNABLE, 0);
7521	if (err < 0)
7522		return err;
7523	snd_pcm_lock(pcm->fast_op_arg);
7524	result = __snd_pcm_mmap_commit(pcm, offset, frames);
7525	snd_pcm_unlock(pcm->fast_op_arg);
7526	return result;
7527}
7528
7529#ifndef DOC_HIDDEN
7530/* locked version*/
7531snd_pcm_sframes_t __snd_pcm_mmap_commit(snd_pcm_t *pcm,
7532					snd_pcm_uframes_t offset,
7533					snd_pcm_uframes_t frames)
7534{
7535	assert(pcm);
7536	if (CHECK_SANITY(offset != *pcm->appl.ptr % pcm->buffer_size)) {
7537		SNDMSG("commit offset (%ld) doesn't match with appl_ptr (%ld) %% buf_size (%ld)",
7538		       offset, *pcm->appl.ptr, pcm->buffer_size);
7539		return -EPIPE;
7540	}
7541	if (CHECK_SANITY(frames > snd_pcm_mmap_avail(pcm))) {
7542		SNDMSG("commit frames (%ld) overflow (avail = %ld)", frames,
7543		       snd_pcm_mmap_avail(pcm));
7544		return -EPIPE;
7545	}
7546	if (pcm->fast_ops->mmap_commit)
7547		return pcm->fast_ops->mmap_commit(pcm->fast_op_arg, offset, frames);
7548	else
7549		return -ENOSYS;
7550}
7551
7552int _snd_pcm_poll_descriptor(snd_pcm_t *pcm)
7553{
7554	assert(pcm);
7555	return pcm->poll_fd;
7556}
7557
7558void snd_pcm_areas_from_buf(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas,
7559			    void *buf)
7560{
7561	unsigned int channel;
7562	unsigned int channels;
7563
7564	snd_pcm_lock(pcm);
7565	channels = pcm->channels;
7566	for (channel = 0; channel < channels; ++channel, ++areas) {
7567		areas->addr = buf;
7568		areas->first = channel * pcm->sample_bits;
7569		areas->step = pcm->frame_bits;
7570	}
7571	snd_pcm_unlock(pcm);
7572}
7573
7574void snd_pcm_areas_from_bufs(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas,
7575			     void **bufs)
7576{
7577	unsigned int channel;
7578	unsigned int channels;
7579
7580	snd_pcm_lock(pcm);
7581	channels = pcm->channels;
7582	for (channel = 0; channel < channels; ++channel, ++areas, ++bufs) {
7583		areas->addr = *bufs;
7584		areas->first = 0;
7585		areas->step = pcm->sample_bits;
7586	}
7587	snd_pcm_unlock(pcm);
7588}
7589
7590snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas,
7591				     snd_pcm_uframes_t offset, snd_pcm_uframes_t size,
7592				     snd_pcm_xfer_areas_func_t func)
7593{
7594	snd_pcm_uframes_t xfer = 0;
7595	snd_pcm_sframes_t err = 0;
7596	snd_pcm_state_t state;
7597
7598	if (size == 0)
7599		return 0;
7600
7601	__snd_pcm_lock(pcm->fast_op_arg); /* forced lock */
7602	while (size > 0) {
7603		snd_pcm_uframes_t frames;
7604		snd_pcm_sframes_t avail;
7605	_again:
7606		state = __snd_pcm_state(pcm);
7607		switch (state) {
7608		case SND_PCM_STATE_PREPARED:
7609			err = __snd_pcm_start(pcm);
7610			if (err < 0)
7611				goto _end;
7612			break;
7613		case SND_PCM_STATE_RUNNING:
7614			err = __snd_pcm_hwsync(pcm);
7615			if (err < 0)
7616				goto _end;
7617			break;
7618		case SND_PCM_STATE_DRAINING:
7619		case SND_PCM_STATE_PAUSED:
7620			break;
7621		default:
7622			err = pcm_state_to_error(state);
7623			if (!err)
7624				err = -EBADFD;
7625			goto _end;
7626		}
7627		avail = __snd_pcm_avail_update(pcm);
7628		if (avail < 0) {
7629			err = avail;
7630			goto _end;
7631		}
7632		if (avail == 0) {
7633			if (state == SND_PCM_STATE_DRAINING)
7634				goto _end;
7635			if (pcm->mode & SND_PCM_NONBLOCK) {
7636				err = -EAGAIN;
7637				goto _end;
7638			}
7639
7640			err = __snd_pcm_wait_in_lock(pcm, SND_PCM_WAIT_IO);
7641			if (err < 0)
7642				break;
7643			goto _again;
7644
7645		}
7646		frames = size;
7647		if (frames > (snd_pcm_uframes_t) avail)
7648			frames = avail;
7649		if (! frames)
7650			break;
7651		err = func(pcm, areas, offset, frames);
7652		if (err < 0)
7653			break;
7654		frames = err;
7655		offset += frames;
7656		size -= frames;
7657		xfer += frames;
7658	}
7659 _end:
7660	__snd_pcm_unlock(pcm->fast_op_arg);
7661	return xfer > 0 ? (snd_pcm_sframes_t) xfer : snd_pcm_check_error(pcm, err);
7662}
7663
7664snd_pcm_sframes_t snd_pcm_write_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas,
7665				      snd_pcm_uframes_t offset, snd_pcm_uframes_t size,
7666				      snd_pcm_xfer_areas_func_t func)
7667{
7668	snd_pcm_uframes_t xfer = 0;
7669	snd_pcm_sframes_t err = 0;
7670	snd_pcm_state_t state;
7671
7672	if (size == 0)
7673		return 0;
7674
7675	__snd_pcm_lock(pcm->fast_op_arg); /* forced lock */
7676	while (size > 0) {
7677		snd_pcm_uframes_t frames;
7678		snd_pcm_sframes_t avail;
7679	_again:
7680		state = __snd_pcm_state(pcm);
7681		switch (state) {
7682		case SND_PCM_STATE_PREPARED:
7683		case SND_PCM_STATE_PAUSED:
7684			break;
7685		case SND_PCM_STATE_RUNNING:
7686			err = __snd_pcm_hwsync(pcm);
7687			if (err < 0)
7688				goto _end;
7689			break;
7690		default:
7691			err = pcm_state_to_error(state);
7692			if (!err)
7693				err = -EBADFD;
7694			goto _end;
7695		}
7696		avail = __snd_pcm_avail_update(pcm);
7697		if (avail < 0) {
7698			err = avail;
7699			goto _end;
7700		}
7701		if (state == SND_PCM_STATE_RUNNING &&
7702		    size > (snd_pcm_uframes_t)avail) {
7703			if (snd_pcm_may_wait_for_avail_min(pcm, avail)) {
7704				if (pcm->mode & SND_PCM_NONBLOCK) {
7705					err = -EAGAIN;
7706					goto _end;
7707				}
7708
7709				err = snd_pcm_wait_nocheck(pcm, SND_PCM_WAIT_IO);
7710				if (err < 0)
7711					break;
7712				goto _again;
7713			}
7714			/* the snd_pcm_may_wait_for_avail_min may check against the
7715			 * updated hw.ptr (slaves), get the avail again here
7716			 */
7717			avail = __snd_pcm_avail_update(pcm);
7718			if (avail < 0) {
7719				err = avail;
7720				goto _end;
7721			}
7722		}
7723		frames = size;
7724		if (frames > (snd_pcm_uframes_t) avail)
7725			frames = avail;
7726		if (! frames)
7727			break;
7728		err = func(pcm, areas, offset, frames);
7729		if (err < 0)
7730			break;
7731		frames = err;
7732		if (state == SND_PCM_STATE_PREPARED) {
7733			snd_pcm_sframes_t hw_avail = pcm->buffer_size - avail;
7734			hw_avail += frames;
7735			/* some plugins might automatically start the stream */
7736			state = __snd_pcm_state(pcm);
7737			if (state == SND_PCM_STATE_PREPARED &&
7738			    hw_avail >= 0 &&
7739			    (snd_pcm_uframes_t) hw_avail >= pcm->start_threshold) {
7740				err = __snd_pcm_start(pcm);
7741				if (err < 0)
7742					goto _end;
7743			}
7744		}
7745		offset += frames;
7746		size -= frames;
7747		xfer += frames;
7748	}
7749 _end:
7750	__snd_pcm_unlock(pcm->fast_op_arg);
7751	return xfer > 0 ? (snd_pcm_sframes_t) xfer : snd_pcm_check_error(pcm, err);
7752}
7753
7754snd_pcm_uframes_t _snd_pcm_mmap_hw_ptr(snd_pcm_t *pcm)
7755{
7756	return *pcm->hw.ptr;
7757}
7758
7759snd_pcm_uframes_t _snd_pcm_boundary(snd_pcm_t *pcm)
7760{
7761	return pcm->boundary;
7762}
7763
7764#ifndef DOC_HIDDEN
7765link_warning(_snd_pcm_mmap_hw_ptr, "Warning: _snd_pcm_mmap_hw_ptr() is deprecated, consider to not use this function");
7766link_warning(_snd_pcm_boundary, "Warning: _snd_pcm_boundary() is deprecated, consider to use snd_pcm_sw_params_current()");
7767#endif
7768
7769static const char *const names[SND_PCM_HW_PARAM_LAST_INTERVAL + 1] = {
7770	[SND_PCM_HW_PARAM_FORMAT] = "format",
7771	[SND_PCM_HW_PARAM_CHANNELS] = "channels",
7772	[SND_PCM_HW_PARAM_RATE] = "rate",
7773	[SND_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
7774	[SND_PCM_HW_PARAM_PERIOD_SIZE] = "period_size",
7775	[SND_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time",
7776	[SND_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size",
7777	[SND_PCM_HW_PARAM_PERIODS] = "periods"
7778};
7779
7780int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
7781		       snd_config_t **_pcm_conf, unsigned int count, ...)
7782{
7783	snd_config_iterator_t i, next;
7784	const char *str;
7785	struct {
7786		unsigned int index;
7787		int flags;
7788		void *ptr;
7789		int present;
7790	} fields[count];
7791	unsigned int k;
7792	snd_config_t *pcm_conf = NULL;
7793	int err;
7794	int to_free = 0;
7795	va_list args;
7796	assert(root);
7797	assert(conf);
7798	assert(_pcm_conf);
7799	if (snd_config_get_string(conf, &str) >= 0) {
7800		err = snd_config_search_definition(root, "pcm_slave", str, &conf);
7801		if (err < 0) {
7802			SNDERR("Invalid slave definition");
7803			return -EINVAL;
7804		}
7805		to_free = 1;
7806	}
7807	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
7808		SNDERR("Invalid slave definition");
7809		err = -EINVAL;
7810		goto _err;
7811	}
7812	va_start(args, count);
7813	for (k = 0; k < count; ++k) {
7814		fields[k].index = va_arg(args, int);
7815		fields[k].flags = va_arg(args, int);
7816		fields[k].ptr = va_arg(args, void *);
7817		fields[k].present = 0;
7818	}
7819	va_end(args);
7820	snd_config_for_each(i, next, conf) {
7821		snd_config_t *n = snd_config_iterator_entry(i);
7822		const char *id;
7823		if (snd_config_get_id(n, &id) < 0)
7824			continue;
7825		if (strcmp(id, "comment") == 0)
7826			continue;
7827		if (strcmp(id, "pcm") == 0) {
7828			if (pcm_conf != NULL)
7829				snd_config_delete(pcm_conf);
7830			if ((err = snd_config_copy(&pcm_conf, n)) < 0)
7831				goto _err;
7832			continue;
7833		}
7834		for (k = 0; k < count; ++k) {
7835			unsigned int idx = fields[k].index;
7836			long v;
7837			assert(idx < SND_PCM_HW_PARAM_LAST_INTERVAL);
7838			assert(names[idx]);
7839			if (strcmp(id, names[idx]) != 0)
7840				continue;
7841			switch (idx) {
7842			case SND_PCM_HW_PARAM_FORMAT:
7843			{
7844				snd_pcm_format_t f;
7845				err = snd_config_get_string(n, &str);
7846				if (err < 0) {
7847				_invalid:
7848					SNDERR("invalid type for %s", id);
7849					goto _err;
7850				}
7851				if ((fields[k].flags & SCONF_UNCHANGED) &&
7852				    strcasecmp(str, "unchanged") == 0) {
7853					*(snd_pcm_format_t*)fields[k].ptr = (snd_pcm_format_t) -2;
7854					break;
7855				}
7856				f = snd_pcm_format_value(str);
7857				if (f == SND_PCM_FORMAT_UNKNOWN) {
7858					SNDERR("unknown format %s", str);
7859					err = -EINVAL;
7860					goto _err;
7861				}
7862				*(snd_pcm_format_t*)fields[k].ptr = f;
7863				break;
7864			}
7865			default:
7866				if ((fields[k].flags & SCONF_UNCHANGED)) {
7867					err = snd_config_get_string(n, &str);
7868					if (err >= 0 &&
7869					    strcasecmp(str, "unchanged") == 0) {
7870						*(int*)fields[k].ptr = -2;
7871						break;
7872					}
7873				}
7874				err = snd_config_get_integer(n, &v);
7875				if (err < 0)
7876					goto _invalid;
7877				*(int*)fields[k].ptr = v;
7878				break;
7879			}
7880			fields[k].present = 1;
7881			break;
7882		}
7883		if (k < count)
7884			continue;
7885		SNDERR("Unknown field %s", id);
7886		err = -EINVAL;
7887		goto _err;
7888	}
7889	if (!pcm_conf) {
7890		SNDERR("missing field pcm");
7891		err = -EINVAL;
7892		goto _err;
7893	}
7894	for (k = 0; k < count; ++k) {
7895		if ((fields[k].flags & SCONF_MANDATORY) && !fields[k].present) {
7896			SNDERR("missing field %s", names[fields[k].index]);
7897			err = -EINVAL;
7898			goto _err;
7899		}
7900	}
7901	*_pcm_conf = pcm_conf;
7902	pcm_conf = NULL;
7903	err = 0;
7904 _err:
7905 	if (pcm_conf)
7906 		snd_config_delete(pcm_conf);
7907	if (to_free)
7908		snd_config_delete(conf);
7909	return err;
7910}
7911
7912static void snd_pcm_set_ptr(snd_pcm_t *pcm, snd_pcm_rbptr_t *rbptr,
7913			    volatile snd_pcm_uframes_t *hw_ptr, int fd, off_t offset)
7914{
7915	rbptr->master = NULL;	/* I'm master */
7916	rbptr->ptr = hw_ptr;
7917	rbptr->fd = fd;
7918	rbptr->offset = offset;
7919	if (rbptr->changed)
7920		rbptr->changed(pcm, NULL);
7921}
7922
7923void snd_pcm_set_hw_ptr(snd_pcm_t *pcm, volatile snd_pcm_uframes_t *hw_ptr, int fd, off_t offset)
7924{
7925	assert(pcm);
7926	assert(hw_ptr);
7927	snd_pcm_set_ptr(pcm, &pcm->hw, hw_ptr, fd, offset);
7928}
7929
7930void snd_pcm_set_appl_ptr(snd_pcm_t *pcm, volatile snd_pcm_uframes_t *appl_ptr, int fd, off_t offset)
7931{
7932	assert(pcm);
7933	assert(appl_ptr);
7934	snd_pcm_set_ptr(pcm, &pcm->appl, appl_ptr, fd, offset);
7935}
7936
7937static void snd_pcm_link_ptr(snd_pcm_t *pcm, snd_pcm_rbptr_t *pcm_rbptr,
7938			     snd_pcm_t *slave, snd_pcm_rbptr_t *slave_rbptr)
7939{
7940	snd_pcm_t **a;
7941	int idx;
7942
7943	a = slave_rbptr->link_dst;
7944	for (idx = 0; idx < slave_rbptr->link_dst_count; idx++)
7945		if (a[idx] == NULL) {
7946			a[idx] = pcm;
7947			goto __found_free_place;
7948		}
7949	a = realloc(a, sizeof(snd_pcm_t *) * (slave_rbptr->link_dst_count + 1));
7950	if (a == NULL) {
7951		pcm_rbptr->ptr = NULL;
7952		pcm_rbptr->fd = -1;
7953		pcm_rbptr->offset = 0UL;
7954		return;
7955	}
7956	a[slave_rbptr->link_dst_count++] = pcm;
7957      __found_free_place:
7958	pcm_rbptr->master = slave_rbptr->master ? slave_rbptr->master : slave;
7959	pcm_rbptr->ptr = slave_rbptr->ptr;
7960	pcm_rbptr->fd = slave_rbptr->fd;
7961	pcm_rbptr->offset = slave_rbptr->offset;
7962	slave_rbptr->link_dst = a;
7963	if (pcm_rbptr->changed)
7964		pcm_rbptr->changed(pcm, slave);
7965}
7966
7967static void snd_pcm_unlink_ptr(snd_pcm_t *pcm, snd_pcm_rbptr_t *pcm_rbptr,
7968			       snd_pcm_t *slave, snd_pcm_rbptr_t *slave_rbptr)
7969{
7970	snd_pcm_t **a;
7971	int idx;
7972
7973	a = slave_rbptr->link_dst;
7974	for (idx = 0; idx < slave_rbptr->link_dst_count; idx++) {
7975		if (a[idx] == pcm) {
7976			a[idx] = NULL;
7977			goto __found;
7978		}
7979	}
7980	/* assert(0); */
7981	return;
7982
7983      __found:
7984      	pcm_rbptr->master = NULL;
7985	pcm_rbptr->ptr = NULL;
7986	pcm_rbptr->fd = -1;
7987	pcm_rbptr->offset = 0UL;
7988	if (pcm_rbptr->changed)
7989		pcm_rbptr->changed(pcm, slave);
7990}
7991
7992void snd_pcm_link_hw_ptr(snd_pcm_t *pcm, snd_pcm_t *slave)
7993{
7994	assert(pcm);
7995	assert(slave);
7996	snd_pcm_link_ptr(pcm, &pcm->hw, slave, &slave->hw);
7997}
7998
7999void snd_pcm_link_appl_ptr(snd_pcm_t *pcm, snd_pcm_t *slave)
8000{
8001	assert(pcm);
8002	assert(slave);
8003	snd_pcm_link_ptr(pcm, &pcm->appl, slave, &slave->appl);
8004}
8005
8006void snd_pcm_unlink_hw_ptr(snd_pcm_t *pcm, snd_pcm_t *slave)
8007{
8008	assert(pcm);
8009	assert(slave);
8010	snd_pcm_unlink_ptr(pcm, &pcm->hw, slave, &slave->hw);
8011}
8012
8013void snd_pcm_unlink_appl_ptr(snd_pcm_t *pcm, snd_pcm_t *slave)
8014{
8015	assert(pcm);
8016	assert(slave);
8017	snd_pcm_unlink_ptr(pcm, &pcm->appl, slave, &slave->appl);
8018}
8019
8020#endif /* DOC_HIDDEN */
8021
8022/*
8023 *
8024 */
8025
8026#ifndef DOC_HIDDEN
8027
8028#ifdef USE_VERSIONED_SYMBOLS
8029
8030#define OBSOLETE1(name, what, new) \
8031  default_symbol_version(__##name, name, new); \
8032  symbol_version(__old_##name, name, what);
8033
8034#else
8035
8036#define OBSOLETE1(name, what, new) \
8037  use_default_symbol_version(__##name, name, new);
8038
8039#endif /* USE_VERSIONED_SYMBOLS */
8040
8041#define __P_OLD_GET(pfx, name, val_type, ret_type) \
8042EXPORT_SYMBOL ret_type pfx##name(const snd_pcm_hw_params_t *params) \
8043{ \
8044	val_type val; \
8045	if (INTERNAL(name)(params, &val) < 0) \
8046		return 0; \
8047	return (ret_type)val; \
8048}
8049
8050#define __P_OLD_GET1(pfx, name, val_type, ret_type) \
8051EXPORT_SYMBOL ret_type pfx##name(const snd_pcm_hw_params_t *params, int *dir) \
8052{ \
8053	val_type val; \
8054	if (INTERNAL(name)(params, &val, dir) < 0) \
8055		return 0; \
8056	return (ret_type)val; \
8057}
8058
8059#define __OLD_GET(name, val_type, ret_type) __P_OLD_GET(__old_, name, val_type, ret_type)
8060#define __OLD_GET1(name, val_type, ret_type) __P_OLD_GET1(__old_, name, val_type, ret_type)
8061
8062__OLD_GET(snd_pcm_hw_params_get_access, snd_pcm_access_t, int);
8063__OLD_GET(snd_pcm_hw_params_get_format, snd_pcm_format_t, int);
8064__OLD_GET(snd_pcm_hw_params_get_subformat, snd_pcm_subformat_t, int);
8065__OLD_GET(snd_pcm_hw_params_get_channels, unsigned int, int);
8066__OLD_GET1(snd_pcm_hw_params_get_rate, unsigned int, int);
8067__OLD_GET1(snd_pcm_hw_params_get_period_time, unsigned int, int);
8068__OLD_GET1(snd_pcm_hw_params_get_period_size, snd_pcm_uframes_t, snd_pcm_sframes_t);
8069__OLD_GET1(snd_pcm_hw_params_get_periods, unsigned int, int);
8070__OLD_GET1(snd_pcm_hw_params_get_buffer_time, unsigned int, int);
8071__OLD_GET(snd_pcm_hw_params_get_buffer_size, snd_pcm_uframes_t, snd_pcm_sframes_t);
8072__OLD_GET1(snd_pcm_hw_params_get_tick_time, unsigned int, int);
8073
8074__OLD_GET(snd_pcm_hw_params_get_channels_min, unsigned int, unsigned int);
8075__OLD_GET1(snd_pcm_hw_params_get_rate_min, unsigned int, unsigned int);
8076__OLD_GET1(snd_pcm_hw_params_get_period_time_min, unsigned int, unsigned int);
8077__OLD_GET1(snd_pcm_hw_params_get_period_size_min, snd_pcm_uframes_t, snd_pcm_uframes_t);
8078__OLD_GET1(snd_pcm_hw_params_get_periods_min, unsigned int, unsigned int);
8079__OLD_GET1(snd_pcm_hw_params_get_buffer_time_min, unsigned int, unsigned int);
8080__OLD_GET(snd_pcm_hw_params_get_buffer_size_min, snd_pcm_uframes_t, snd_pcm_uframes_t);
8081__OLD_GET1(snd_pcm_hw_params_get_tick_time_min, unsigned int, unsigned int);
8082
8083__OLD_GET(snd_pcm_hw_params_get_channels_max, unsigned int, unsigned int);
8084__OLD_GET1(snd_pcm_hw_params_get_rate_max, unsigned int, unsigned int);
8085__OLD_GET1(snd_pcm_hw_params_get_period_time_max, unsigned int, unsigned int);
8086__OLD_GET1(snd_pcm_hw_params_get_period_size_max, snd_pcm_uframes_t, snd_pcm_uframes_t);
8087__OLD_GET1(snd_pcm_hw_params_get_periods_max, unsigned int, unsigned int);
8088__OLD_GET1(snd_pcm_hw_params_get_buffer_time_max, unsigned int, unsigned int);
8089__OLD_GET(snd_pcm_hw_params_get_buffer_size_max, snd_pcm_uframes_t, snd_pcm_uframes_t);
8090__OLD_GET1(snd_pcm_hw_params_get_tick_time_max, unsigned int, unsigned int);
8091
8092#define __P_OLD_NEAR(pfx, name, ret_type) \
8093EXPORT_SYMBOL ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, ret_type val) \
8094{ \
8095	if (INTERNAL(name)(pcm, params, &val) < 0) \
8096		return 0; \
8097	return (ret_type)val; \
8098}
8099
8100#define __P_OLD_NEAR1(pfx, name, ret_type) \
8101EXPORT_SYMBOL ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, ret_type val, int *dir) \
8102{ \
8103	if (INTERNAL(name)(pcm, params, &val, dir) < 0) \
8104		return 0; \
8105	return (ret_type)val; \
8106}
8107
8108#define __OLD_NEAR(name, ret_type) __P_OLD_NEAR(__old_, name, ret_type)
8109#define __OLD_NEAR1(name, ret_type) __P_OLD_NEAR1(__old_, name, ret_type)
8110
8111__OLD_NEAR(snd_pcm_hw_params_set_channels_near, unsigned int);
8112__OLD_NEAR1(snd_pcm_hw_params_set_rate_near, unsigned int);
8113__OLD_NEAR1(snd_pcm_hw_params_set_period_time_near, unsigned int);
8114__OLD_NEAR1(snd_pcm_hw_params_set_period_size_near, snd_pcm_uframes_t);
8115__OLD_NEAR1(snd_pcm_hw_params_set_periods_near, unsigned int);
8116__OLD_NEAR1(snd_pcm_hw_params_set_buffer_time_near, unsigned int);
8117__OLD_NEAR(snd_pcm_hw_params_set_buffer_size_near, snd_pcm_uframes_t);
8118__OLD_NEAR1(snd_pcm_hw_params_set_tick_time_near, unsigned int);
8119
8120#define __P_OLD_SET_FL(pfx, name, ret_type) \
8121EXPORT_SYMBOL ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) \
8122{ \
8123	ret_type val; \
8124	if (INTERNAL(name)(pcm, params, &val) < 0) \
8125		return 0; \
8126	return (ret_type)val; \
8127}
8128
8129#define __P_OLD_SET_FL1(pfx, name, ret_type) \
8130EXPORT_SYMBOL ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir) \
8131{ \
8132	ret_type val; \
8133	if (INTERNAL(name)(pcm, params, &val, dir) < 0) \
8134		return 0; \
8135	return (ret_type)val; \
8136}
8137
8138#define __OLD_SET_FL(name, ret_type) __P_OLD_SET_FL(__old_, name, ret_type)
8139#define __OLD_SET_FL1(name, ret_type) __P_OLD_SET_FL1(__old_, name, ret_type)
8140
8141__OLD_SET_FL(snd_pcm_hw_params_set_access_first, snd_pcm_access_t);
8142__OLD_SET_FL(snd_pcm_hw_params_set_format_first, snd_pcm_format_t);
8143__OLD_SET_FL(snd_pcm_hw_params_set_subformat_first, snd_pcm_subformat_t);
8144__OLD_SET_FL(snd_pcm_hw_params_set_channels_first, unsigned int);
8145__OLD_SET_FL1(snd_pcm_hw_params_set_rate_first, unsigned int);
8146__OLD_SET_FL1(snd_pcm_hw_params_set_period_time_first, unsigned int);
8147__OLD_SET_FL1(snd_pcm_hw_params_set_period_size_first, snd_pcm_uframes_t);
8148__OLD_SET_FL1(snd_pcm_hw_params_set_periods_first, unsigned int);
8149__OLD_SET_FL1(snd_pcm_hw_params_set_buffer_time_first, unsigned int);
8150__OLD_SET_FL(snd_pcm_hw_params_set_buffer_size_first, snd_pcm_uframes_t);
8151__OLD_SET_FL1(snd_pcm_hw_params_set_tick_time_first, unsigned int);
8152
8153__OLD_SET_FL(snd_pcm_hw_params_set_access_last, snd_pcm_access_t);
8154__OLD_SET_FL(snd_pcm_hw_params_set_format_last, snd_pcm_format_t);
8155__OLD_SET_FL(snd_pcm_hw_params_set_subformat_last, snd_pcm_subformat_t);
8156__OLD_SET_FL(snd_pcm_hw_params_set_channels_last, unsigned int);
8157__OLD_SET_FL1(snd_pcm_hw_params_set_rate_last, unsigned int);
8158__OLD_SET_FL1(snd_pcm_hw_params_set_period_time_last, unsigned int);
8159__OLD_SET_FL1(snd_pcm_hw_params_set_period_size_last, snd_pcm_uframes_t);
8160__OLD_SET_FL1(snd_pcm_hw_params_set_periods_last, unsigned int);
8161__OLD_SET_FL1(snd_pcm_hw_params_set_buffer_time_last, unsigned int);
8162__OLD_SET_FL(snd_pcm_hw_params_set_buffer_size_last, snd_pcm_uframes_t);
8163__OLD_SET_FL1(snd_pcm_hw_params_set_tick_time_last, unsigned int);
8164
8165#define __P_OLD_GET_SW(pfx, name, ret_type) \
8166EXPORT_SYMBOL ret_type pfx##name(snd_pcm_sw_params_t *params) \
8167{ \
8168	ret_type val; \
8169	if (INTERNAL(name)(params, &val) < 0) \
8170		return 0; \
8171	return (ret_type)val; \
8172}
8173
8174#define __OLD_GET_SW(name, ret_type) __P_OLD_GET_SW(__old_, name, ret_type)
8175
8176__OLD_GET_SW(snd_pcm_sw_params_get_tstamp_mode, snd_pcm_tstamp_t);
8177__OLD_GET_SW(snd_pcm_sw_params_get_sleep_min, unsigned int);
8178__OLD_GET_SW(snd_pcm_sw_params_get_avail_min, snd_pcm_uframes_t);
8179__OLD_GET_SW(snd_pcm_sw_params_get_xfer_align, snd_pcm_uframes_t);
8180__OLD_GET_SW(snd_pcm_sw_params_get_start_threshold, snd_pcm_uframes_t);
8181__OLD_GET_SW(snd_pcm_sw_params_get_stop_threshold, snd_pcm_uframes_t);
8182__OLD_GET_SW(snd_pcm_sw_params_get_silence_threshold, snd_pcm_uframes_t);
8183__OLD_GET_SW(snd_pcm_sw_params_get_silence_size, snd_pcm_uframes_t);
8184
8185OBSOLETE1(snd_pcm_hw_params_get_access, ALSA_0.9, ALSA_0.9.0rc4);
8186OBSOLETE1(snd_pcm_hw_params_set_access_first, ALSA_0.9, ALSA_0.9.0rc4);
8187OBSOLETE1(snd_pcm_hw_params_set_access_last, ALSA_0.9, ALSA_0.9.0rc4);
8188
8189OBSOLETE1(snd_pcm_hw_params_get_format, ALSA_0.9, ALSA_0.9.0rc4);
8190OBSOLETE1(snd_pcm_hw_params_set_format_first, ALSA_0.9, ALSA_0.9.0rc4);
8191OBSOLETE1(snd_pcm_hw_params_set_format_last, ALSA_0.9, ALSA_0.9.0rc4);
8192
8193OBSOLETE1(snd_pcm_hw_params_get_subformat, ALSA_0.9, ALSA_0.9.0rc4);
8194OBSOLETE1(snd_pcm_hw_params_set_subformat_first, ALSA_0.9, ALSA_0.9.0rc4);
8195OBSOLETE1(snd_pcm_hw_params_set_subformat_last, ALSA_0.9, ALSA_0.9.0rc4);
8196
8197OBSOLETE1(snd_pcm_hw_params_get_channels, ALSA_0.9, ALSA_0.9.0rc4);
8198OBSOLETE1(snd_pcm_hw_params_get_channels_min, ALSA_0.9, ALSA_0.9.0rc4);
8199OBSOLETE1(snd_pcm_hw_params_get_channels_max, ALSA_0.9, ALSA_0.9.0rc4);
8200OBSOLETE1(snd_pcm_hw_params_set_channels_near, ALSA_0.9, ALSA_0.9.0rc4);
8201OBSOLETE1(snd_pcm_hw_params_set_channels_first, ALSA_0.9, ALSA_0.9.0rc4);
8202OBSOLETE1(snd_pcm_hw_params_set_channels_last, ALSA_0.9, ALSA_0.9.0rc4);
8203
8204OBSOLETE1(snd_pcm_hw_params_get_rate, ALSA_0.9, ALSA_0.9.0rc4);
8205OBSOLETE1(snd_pcm_hw_params_get_rate_min, ALSA_0.9, ALSA_0.9.0rc4);
8206OBSOLETE1(snd_pcm_hw_params_get_rate_max, ALSA_0.9, ALSA_0.9.0rc4);
8207OBSOLETE1(snd_pcm_hw_params_set_rate_near, ALSA_0.9, ALSA_0.9.0rc4);
8208OBSOLETE1(snd_pcm_hw_params_set_rate_first, ALSA_0.9, ALSA_0.9.0rc4);
8209OBSOLETE1(snd_pcm_hw_params_set_rate_last, ALSA_0.9, ALSA_0.9.0rc4);
8210
8211OBSOLETE1(snd_pcm_hw_params_get_period_time, ALSA_0.9, ALSA_0.9.0rc4);
8212OBSOLETE1(snd_pcm_hw_params_get_period_time_min, ALSA_0.9, ALSA_0.9.0rc4);
8213OBSOLETE1(snd_pcm_hw_params_get_period_time_max, ALSA_0.9, ALSA_0.9.0rc4);
8214OBSOLETE1(snd_pcm_hw_params_set_period_time_near, ALSA_0.9, ALSA_0.9.0rc4);
8215OBSOLETE1(snd_pcm_hw_params_set_period_time_first, ALSA_0.9, ALSA_0.9.0rc4);
8216OBSOLETE1(snd_pcm_hw_params_set_period_time_last, ALSA_0.9, ALSA_0.9.0rc4);
8217
8218OBSOLETE1(snd_pcm_hw_params_get_period_size, ALSA_0.9, ALSA_0.9.0rc4);
8219OBSOLETE1(snd_pcm_hw_params_get_period_size_min, ALSA_0.9, ALSA_0.9.0rc4);
8220OBSOLETE1(snd_pcm_hw_params_get_period_size_max, ALSA_0.9, ALSA_0.9.0rc4);
8221OBSOLETE1(snd_pcm_hw_params_set_period_size_near, ALSA_0.9, ALSA_0.9.0rc4);
8222OBSOLETE1(snd_pcm_hw_params_set_period_size_first, ALSA_0.9, ALSA_0.9.0rc4);
8223OBSOLETE1(snd_pcm_hw_params_set_period_size_last, ALSA_0.9, ALSA_0.9.0rc4);
8224
8225OBSOLETE1(snd_pcm_hw_params_get_periods, ALSA_0.9, ALSA_0.9.0rc4);
8226OBSOLETE1(snd_pcm_hw_params_get_periods_min, ALSA_0.9, ALSA_0.9.0rc4);
8227OBSOLETE1(snd_pcm_hw_params_get_periods_max, ALSA_0.9, ALSA_0.9.0rc4);
8228OBSOLETE1(snd_pcm_hw_params_set_periods_near, ALSA_0.9, ALSA_0.9.0rc4);
8229OBSOLETE1(snd_pcm_hw_params_set_periods_first, ALSA_0.9, ALSA_0.9.0rc4);
8230OBSOLETE1(snd_pcm_hw_params_set_periods_last, ALSA_0.9, ALSA_0.9.0rc4);
8231
8232OBSOLETE1(snd_pcm_hw_params_get_buffer_time, ALSA_0.9, ALSA_0.9.0rc4);
8233OBSOLETE1(snd_pcm_hw_params_get_buffer_time_min, ALSA_0.9, ALSA_0.9.0rc4);
8234OBSOLETE1(snd_pcm_hw_params_get_buffer_time_max, ALSA_0.9, ALSA_0.9.0rc4);
8235OBSOLETE1(snd_pcm_hw_params_set_buffer_time_near, ALSA_0.9, ALSA_0.9.0rc4);
8236OBSOLETE1(snd_pcm_hw_params_set_buffer_time_first, ALSA_0.9, ALSA_0.9.0rc4);
8237OBSOLETE1(snd_pcm_hw_params_set_buffer_time_last, ALSA_0.9, ALSA_0.9.0rc4);
8238
8239OBSOLETE1(snd_pcm_hw_params_get_buffer_size, ALSA_0.9, ALSA_0.9.0rc4);
8240OBSOLETE1(snd_pcm_hw_params_get_buffer_size_min, ALSA_0.9, ALSA_0.9.0rc4);
8241OBSOLETE1(snd_pcm_hw_params_get_buffer_size_max, ALSA_0.9, ALSA_0.9.0rc4);
8242OBSOLETE1(snd_pcm_hw_params_set_buffer_size_near, ALSA_0.9, ALSA_0.9.0rc4);
8243OBSOLETE1(snd_pcm_hw_params_set_buffer_size_first, ALSA_0.9, ALSA_0.9.0rc4);
8244OBSOLETE1(snd_pcm_hw_params_set_buffer_size_last, ALSA_0.9, ALSA_0.9.0rc4);
8245
8246OBSOLETE1(snd_pcm_hw_params_get_tick_time, ALSA_0.9, ALSA_0.9.0rc4);
8247OBSOLETE1(snd_pcm_hw_params_get_tick_time_min, ALSA_0.9, ALSA_0.9.0rc4);
8248OBSOLETE1(snd_pcm_hw_params_get_tick_time_max, ALSA_0.9, ALSA_0.9.0rc4);
8249OBSOLETE1(snd_pcm_hw_params_set_tick_time_near, ALSA_0.9, ALSA_0.9.0rc4);
8250OBSOLETE1(snd_pcm_hw_params_set_tick_time_first, ALSA_0.9, ALSA_0.9.0rc4);
8251OBSOLETE1(snd_pcm_hw_params_set_tick_time_last, ALSA_0.9, ALSA_0.9.0rc4);
8252
8253OBSOLETE1(snd_pcm_sw_params_get_tstamp_mode, ALSA_0.9, ALSA_0.9.0rc4);
8254OBSOLETE1(snd_pcm_sw_params_get_sleep_min, ALSA_0.9, ALSA_0.9.0rc4);
8255OBSOLETE1(snd_pcm_sw_params_get_avail_min, ALSA_0.9, ALSA_0.9.0rc4);
8256OBSOLETE1(snd_pcm_sw_params_get_xfer_align, ALSA_0.9, ALSA_0.9.0rc4);
8257OBSOLETE1(snd_pcm_sw_params_get_start_threshold, ALSA_0.9, ALSA_0.9.0rc4);
8258OBSOLETE1(snd_pcm_sw_params_get_stop_threshold, ALSA_0.9, ALSA_0.9.0rc4);
8259OBSOLETE1(snd_pcm_sw_params_get_silence_threshold, ALSA_0.9, ALSA_0.9.0rc4);
8260OBSOLETE1(snd_pcm_sw_params_get_silence_size, ALSA_0.9, ALSA_0.9.0rc4);
8261
8262#endif /* DOC_HIDDEN */
8263
8264static int chmap_equal(const snd_pcm_chmap_t *a, const snd_pcm_chmap_t *b)
8265{
8266	if (a->channels != b->channels)
8267		return 0;
8268	return !memcmp(a->pos, b->pos, a->channels * sizeof(a->pos[0]));
8269}
8270
8271/**
8272 * \!brief Query the available channel maps
8273 * \param pcm PCM handle to query
8274 * \return the NULL-terminated array of integer pointers, each of
8275 * which contains the channel map. A channel map is represented by an
8276 * integer array, beginning with the channel map type, followed by the
8277 * number of channels, and the position of each channel. Return NULL
8278 * in case of an error.
8279 *
8280 * Note: the caller is requested to release the returned value via
8281 * snd_pcm_free_chmaps().
8282 */
8283snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm)
8284{
8285	if (!pcm->ops->query_chmaps)
8286		return NULL;
8287	return pcm->ops->query_chmaps(pcm);
8288}
8289
8290/**
8291 * \!brief Release the channel map array allocated via #snd_pcm_query_chmaps
8292 * \param maps the array pointer to release
8293 */
8294void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps)
8295{
8296	snd_pcm_chmap_query_t **p;
8297	if (!maps)
8298		return;
8299	for (p = maps; *p; p++)
8300		free(*p);
8301	free(maps);
8302}
8303
8304/**
8305 * \!brief Get the current channel map
8306 * \param pcm PCM instance
8307 * \return the current channel map, or NULL if error
8308 *
8309 * Note: the caller is requested to release the returned value via free()
8310 */
8311snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm)
8312{
8313	if (!pcm->ops->get_chmap)
8314		return NULL;
8315	return pcm->ops->get_chmap(pcm);
8316}
8317
8318/**
8319 * \!brief Configure the current channel map
8320 * \param pcm PCM instance
8321 * \param map the channel map to write
8322 * \return zero if succeeded, or a negative error code
8323 */
8324int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
8325{
8326	const snd_pcm_chmap_t *oldmap;
8327	int nochange;
8328
8329	oldmap = snd_pcm_get_chmap(pcm);
8330	nochange = (oldmap && chmap_equal(oldmap, map));
8331	free((void *)oldmap);
8332	if (nochange)
8333		return 0;
8334
8335	if (!pcm->ops->set_chmap)
8336		return -ENXIO;
8337	return pcm->ops->set_chmap(pcm, map);
8338}
8339
8340/*
8341 */
8342#ifndef DOC_HIDDEN
8343#define _NAME(n) [SND_CHMAP_TYPE_##n] = #n
8344static const char *chmap_type_names[SND_CHMAP_TYPE_LAST + 1] = {
8345	_NAME(NONE), _NAME(FIXED), _NAME(VAR), _NAME(PAIRED),
8346};
8347#undef _NAME
8348#endif
8349
8350/**
8351 * \!brief Get a name string for a channel map type as query results
8352 * \param val Channel position
8353 * \return The string corresponding to the given type, or NULL
8354 */
8355const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val)
8356{
8357	if (val <= SND_CHMAP_TYPE_LAST)
8358		return chmap_type_names[val];
8359	else
8360		return NULL;
8361}
8362
8363#ifndef DOC_HIDDEN
8364#define _NAME(n) [SND_CHMAP_##n] = #n
8365static const char *chmap_names[SND_CHMAP_LAST + 1] = {
8366	_NAME(UNKNOWN), _NAME(NA), _NAME(MONO),
8367	_NAME(FL), _NAME(FR),
8368	_NAME(RL), _NAME(RR),
8369	_NAME(FC), _NAME(LFE),
8370	_NAME(SL), _NAME(SR),
8371	_NAME(RC), _NAME(FLC), _NAME(FRC), _NAME(RLC), _NAME(RRC),
8372	_NAME(FLW), _NAME(FRW),
8373	_NAME(FLH), _NAME(FCH), _NAME(FRH), _NAME(TC),
8374	_NAME(TFL), _NAME(TFR), _NAME(TFC),
8375	_NAME(TRL), _NAME(TRR), _NAME(TRC),
8376	_NAME(TFLC), _NAME(TFRC), _NAME(TSL), _NAME(TSR),
8377	_NAME(LLFE), _NAME(RLFE),
8378	_NAME(BC), _NAME(BLC), _NAME(BRC),
8379};
8380#undef _NAME
8381#endif
8382
8383/**
8384 * \!brief Get a name string for a standard channel map position
8385 * \param val Channel position
8386 * \return The string corresponding to the given position, or NULL
8387 */
8388const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val)
8389{
8390	if (val <= SND_CHMAP_LAST)
8391		return chmap_names[val];
8392	else
8393		return NULL;
8394}
8395
8396static const char *chmap_long_names[SND_CHMAP_LAST + 1] = {
8397	[SND_CHMAP_UNKNOWN] = "Unknown",
8398	[SND_CHMAP_NA] = "Unused",
8399	[SND_CHMAP_MONO] = "Mono",
8400	[SND_CHMAP_FL] = "Front Left",
8401	[SND_CHMAP_FR] = "Front Right",
8402	[SND_CHMAP_RL] = "Rear Left",
8403	[SND_CHMAP_RR] = "Rear Right",
8404	[SND_CHMAP_FC] = "Front Center",
8405	[SND_CHMAP_LFE] = "LFE",
8406	[SND_CHMAP_SL] = "Side Left",
8407	[SND_CHMAP_SR] = "Side Right",
8408	[SND_CHMAP_RC] = "Rear Center",
8409	[SND_CHMAP_FLC] = "Front Left Center",
8410	[SND_CHMAP_FRC] = "Front Right Center",
8411	[SND_CHMAP_RLC] = "Rear Left Center",
8412	[SND_CHMAP_RRC] = "Rear Right Center",
8413	[SND_CHMAP_FLW] = "Front Left Wide",
8414	[SND_CHMAP_FRW] = "Front Right Wide",
8415	[SND_CHMAP_FLH] = "Front Left High",
8416	[SND_CHMAP_FCH] = "Front Center High",
8417	[SND_CHMAP_FRH] = "Front Right High",
8418	[SND_CHMAP_TC] = "Top Center",
8419	[SND_CHMAP_TFL] = "Top Front Left",
8420	[SND_CHMAP_TFR] = "Top Front Right",
8421	[SND_CHMAP_TFC] = "Top Front Center",
8422	[SND_CHMAP_TRL] = "Top Rear Left",
8423	[SND_CHMAP_TRR] = "Top Rear Right",
8424	[SND_CHMAP_TRC] = "Top Rear Center",
8425	[SND_CHMAP_TFLC] = "Top Front Left Center",
8426	[SND_CHMAP_TFRC] = "Top Front Right Center",
8427	[SND_CHMAP_TSL] = "Top Side Left",
8428	[SND_CHMAP_TSR] = "Top Side Right",
8429	[SND_CHMAP_LLFE] = "Left LFE",
8430	[SND_CHMAP_RLFE] = "Right LFE",
8431	[SND_CHMAP_BC] = "Bottom Center",
8432	[SND_CHMAP_BLC] = "Bottom Left Center",
8433	[SND_CHMAP_BRC] = "Bottom Right Center",
8434};
8435
8436/**
8437 * \!brief Get a longer name string for a standard channel map position
8438 * \param val Channel position
8439 * \return The string corresponding to the given position, or NULL
8440 */
8441const char *snd_pcm_chmap_long_name(enum snd_pcm_chmap_position val)
8442{
8443	if (val <= SND_CHMAP_LAST)
8444		return chmap_long_names[val];
8445	else
8446		return NULL;
8447}
8448
8449/**
8450 * \!brief Print the channels in chmap on the buffer
8451 * \param map The channel map to print
8452 * \param maxlen The maximal length to write (including NUL letter)
8453 * \param buf The buffer to write
8454 * \return The actual string length or a negative error code
8455 */
8456int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf)
8457{
8458	unsigned int i, len = 0;
8459
8460	for (i = 0; i < map->channels; i++) {
8461		unsigned int p = map->pos[i] & SND_CHMAP_POSITION_MASK;
8462		if (i > 0) {
8463			len += snprintf(buf + len, maxlen - len, " ");
8464			if (len >= maxlen)
8465				return -ENOMEM;
8466		}
8467		if (map->pos[i] & SND_CHMAP_DRIVER_SPEC)
8468			len += snprintf(buf + len, maxlen - len, "%d", p);
8469		else {
8470			const char *name = chmap_names[p];
8471			if (name)
8472				len += snprintf(buf + len, maxlen - len,
8473						"%s", name);
8474			else
8475				len += snprintf(buf + len, maxlen - len,
8476						"Ch%d", p);
8477		}
8478		if (len >= maxlen)
8479			return -ENOMEM;
8480		if (map->pos[i] & SND_CHMAP_PHASE_INVERSE) {
8481			len += snprintf(buf + len, maxlen - len, "[INV]");
8482			if (len >= maxlen)
8483				return -ENOMEM;
8484		}
8485	}
8486	return len;
8487}
8488
8489static int str_to_chmap(const char *str, int len)
8490{
8491	int val;
8492	unsigned long v;
8493	char *p;
8494
8495	if (isdigit(*str)) {
8496		v = strtoul(str, &p, 0);
8497		if (v == ULONG_MAX)
8498			return -1;
8499		val = v;
8500		val |= SND_CHMAP_DRIVER_SPEC;
8501		str = p;
8502	} else if (!strncasecmp(str, "ch", 2)) {
8503		v = strtoul(str + 2, &p, 0);
8504		if (v == ULONG_MAX)
8505			return -1;
8506		val = v;
8507		str = p;
8508	} else {
8509		for (val = 0; val <= SND_CHMAP_LAST; val++) {
8510			int slen;
8511			assert(chmap_names[val]);
8512			slen = strlen(chmap_names[val]);
8513			if (slen > len)
8514				continue;
8515			if (!strncasecmp(str, chmap_names[val], slen) &&
8516			    !isalpha(str[slen])) {
8517				str += slen;
8518				break;
8519			}
8520		}
8521		if (val > SND_CHMAP_LAST)
8522			return -1;
8523	}
8524	if (str && !strncasecmp(str, "[INV]", 5))
8525		val |= SND_CHMAP_PHASE_INVERSE;
8526	return val;
8527}
8528
8529/**
8530 * \!brief Convert from string to channel position
8531 * \param str The string to parse
8532 * \return The channel position value or -1 as an error
8533 */
8534unsigned int snd_pcm_chmap_from_string(const char *str)
8535{
8536	return str_to_chmap(str, strlen(str));
8537}
8538
8539/**
8540 * \!brief Convert from string to channel map
8541 * \param str The string to parse
8542 * \return The channel map
8543 *
8544 * Note: the caller is requested to release the returned value via free()
8545 */
8546snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str)
8547{
8548	int i, ch = 0;
8549	int tmp_map[64];
8550	snd_pcm_chmap_t *map;
8551
8552	for (;;) {
8553		const char *p;
8554		int len, val;
8555
8556		if (ch >= (int)(sizeof(tmp_map) / sizeof(tmp_map[0])))
8557			return NULL;
8558		for (p = str; *p && isalnum(*p); p++)
8559			;
8560		len = p - str;
8561		if (!len)
8562			return NULL;
8563		val = str_to_chmap(str, len);
8564		if (val < 0)
8565			return NULL;
8566		str += len;
8567		if (*str == '[') {
8568			if (!strncmp(str, "[INV]", 5)) {
8569				val |= SND_CHMAP_PHASE_INVERSE;
8570				str += 5;
8571			}
8572		}
8573		tmp_map[ch] = val;
8574		ch++;
8575		for (; *str && !isalnum(*str); str++)
8576			;
8577		if (!*str)
8578			break;
8579	}
8580	map = malloc(sizeof(*map) + ch * sizeof(int));
8581	if (!map)
8582		return NULL;
8583	map->channels = ch;
8584	for (i = 0; i < ch; i++)
8585		map->pos[i] = tmp_map[i];
8586	return map;
8587}
8588
8589/* copy a single channel map with the fixed type to chmap_query pointer */
8590static int _copy_to_fixed_query_map(snd_pcm_chmap_query_t **dst,
8591				    const snd_pcm_chmap_t *src)
8592{
8593	*dst = malloc((src->channels + 2) * sizeof(int));
8594	if (!*dst)
8595		return -ENOMEM;
8596	(*dst)->type = SND_CHMAP_TYPE_FIXED;
8597	memcpy(&(*dst)->map, src, (src->channels + 1) * sizeof(int));
8598	return 0;
8599}
8600
8601#ifndef DOC_HIDDEN
8602/* make a chmap_query array from a single channel map */
8603snd_pcm_chmap_query_t **
8604_snd_pcm_make_single_query_chmaps(const snd_pcm_chmap_t *src)
8605{
8606	snd_pcm_chmap_query_t **maps;
8607
8608	maps = calloc(2, sizeof(*maps));
8609	if (!maps)
8610		return NULL;
8611	if (_copy_to_fixed_query_map(maps, src)) {
8612		free(maps);
8613		return NULL;
8614	}
8615	return maps;
8616}
8617
8618/* make a copy of chmap */
8619snd_pcm_chmap_t *_snd_pcm_copy_chmap(const snd_pcm_chmap_t *src)
8620{
8621	snd_pcm_chmap_t *map;
8622
8623	map = malloc((src->channels + 1) * sizeof(int));
8624	if (!map)
8625		return NULL;
8626	memcpy(map, src, (src->channels + 1) * sizeof(int));
8627	return map;
8628}
8629
8630/* make a copy of channel maps */
8631snd_pcm_chmap_query_t **
8632_snd_pcm_copy_chmap_query(snd_pcm_chmap_query_t * const *src)
8633{
8634	snd_pcm_chmap_query_t * const *p;
8635	snd_pcm_chmap_query_t **maps;
8636	int i, nums;
8637
8638	for (nums = 0, p = src; *p; p++)
8639		nums++;
8640
8641	maps = calloc(nums + 1, sizeof(*maps));
8642	if (!maps)
8643		return NULL;
8644	for (i = 0; i < nums; i++) {
8645		maps[i] = malloc((src[i]->map.channels + 2) * sizeof(int));
8646		if (!maps[i]) {
8647			snd_pcm_free_chmaps(maps);
8648			return NULL;
8649		}
8650		memcpy(maps[i], src[i], (src[i]->map.channels + 2) * sizeof(int));
8651	}
8652	return maps;
8653}
8654
8655/* select the channel map with the current PCM channels and make a copy */
8656snd_pcm_chmap_t *
8657_snd_pcm_choose_fixed_chmap(snd_pcm_t *pcm, snd_pcm_chmap_query_t * const *maps)
8658{
8659	snd_pcm_chmap_query_t * const *p;
8660
8661	for (p = maps; *p; p++) {
8662		if ((*p)->map.channels == pcm->channels)
8663			return _snd_pcm_copy_chmap(&(*p)->map);
8664	}
8665	return NULL;
8666}
8667
8668/* make chmap_query array from the config tree;
8669 * conf must be a compound (array)
8670 */
8671snd_pcm_chmap_query_t **
8672_snd_pcm_parse_config_chmaps(snd_config_t *conf)
8673{
8674	snd_pcm_chmap_t *chmap;
8675	snd_pcm_chmap_query_t **maps;
8676	snd_config_iterator_t i, next;
8677	const char *str;
8678	int nums, err;
8679
8680	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
8681		return NULL;
8682
8683	nums = 0;
8684	snd_config_for_each(i, next, conf) {
8685		nums++;
8686	}
8687
8688	maps = calloc(nums + 1, sizeof(*maps));
8689	if (!maps)
8690		return NULL;
8691
8692	nums = 0;
8693	snd_config_for_each(i, next, conf) {
8694		snd_config_t *n = snd_config_iterator_entry(i);
8695		err = snd_config_get_string(n, &str);
8696		if (err < 0)
8697			goto error;
8698		chmap = snd_pcm_chmap_parse_string(str);
8699		if (!chmap)
8700			goto error;
8701		if (_copy_to_fixed_query_map(maps + nums, chmap)) {
8702			free(chmap);
8703			goto error;
8704		}
8705		free(chmap);
8706		nums++;
8707	}
8708	return maps;
8709
8710 error:
8711	snd_pcm_free_chmaps(maps);
8712	return NULL;
8713}
8714#endif /* DOC_HIDDEN */
8715
8716/*
8717 * basic helpers
8718 */
8719
8720
8721/**
8722 * \brief Recover the stream state from an error or suspend
8723 * \param pcm PCM handle
8724 * \param err error number
8725 * \param silent do not print error reason
8726 * \return 0 when error code was handled successfuly, otherwise a negative error code
8727 *
8728 * This a high-level helper function building on other functions.
8729 *
8730 * This functions handles -EINTR (interrupted system call),
8731 * -EPIPE (overrun or underrun) and -ESTRPIPE (stream is suspended)
8732 * error codes trying to prepare given stream for next I/O.
8733 *
8734 * Note that this function returs the original error code when it is not
8735 * handled inside this function (for example -EAGAIN is returned back).
8736 */
8737int snd_pcm_recover(snd_pcm_t *pcm, int err, int silent)
8738{
8739        if (err > 0)
8740                err = -err;
8741        if (err == -EINTR)	/* nothing to do, continue */
8742                return 0;
8743        if (err == -EPIPE) {
8744                const char *s;
8745                if (snd_pcm_stream(pcm) == SND_PCM_STREAM_PLAYBACK)
8746                        s = "underrun";
8747                else
8748                        s = "overrun";
8749                if (!silent)
8750                        SNDERR("%s occurred", s);
8751                err = snd_pcm_prepare(pcm);
8752                if (err < 0) {
8753                        SNDERR("cannot recovery from %s, prepare failed: %s", s, snd_strerror(err));
8754                        return err;
8755                }
8756                return 0;
8757        }
8758        if (err == -ESTRPIPE) {
8759                while ((err = snd_pcm_resume(pcm)) == -EAGAIN)
8760                        /* wait until suspend flag is released */
8761                        poll(NULL, 0, 1000);
8762                if (err < 0) {
8763                        err = snd_pcm_prepare(pcm);
8764                        if (err < 0) {
8765                                SNDERR("cannot recovery from suspend, prepare failed: %s", snd_strerror(err));
8766                                return err;
8767                        }
8768                }
8769                return 0;
8770        }
8771        return err;
8772}
8773
8774/**
8775 * \brief Set the hardware and software parameters in a simple way
8776 * \param pcm PCM handle
8777 * \param format required PCM format
8778 * \param access required PCM access
8779 * \param channels required PCM channels
8780 * \param rate required sample rate in Hz
8781 * \param soft_resample 0 = disallow alsa-lib resample stream, 1 = allow resampling
8782 * \param latency required overall latency in us
8783 * \return 0 on success otherwise a negative error code
8784 */
8785int snd_pcm_set_params(snd_pcm_t *pcm,
8786                       snd_pcm_format_t format,
8787                       snd_pcm_access_t access,
8788                       unsigned int channels,
8789                       unsigned int rate,
8790                       int soft_resample,
8791                       unsigned int latency)
8792{
8793	snd_pcm_hw_params_t params_saved, params = {0};
8794	snd_pcm_sw_params_t swparams = {0};
8795	const char *s = snd_pcm_stream_name(snd_pcm_stream(pcm));
8796	snd_pcm_uframes_t buffer_size, period_size;
8797	unsigned int rrate, period_time;
8798	int err;
8799
8800	assert(pcm);
8801	/* choose all parameters */
8802	err = snd_pcm_hw_params_any(pcm, &params);
8803	if (err < 0) {
8804		SNDERR("Broken configuration for %s: no configurations available",
8805		       s);
8806		return err;
8807        }
8808	/* set software resampling */
8809	err = snd_pcm_hw_params_set_rate_resample(pcm, &params, soft_resample);
8810	if (err < 0) {
8811		SNDERR("Resampling setup failed for %s: %s",
8812		       s, snd_strerror(err));
8813		return err;
8814	}
8815	/* set the selected read/write format */
8816	err = snd_pcm_hw_params_set_access(pcm, &params, access);
8817	if (err < 0) {
8818		SNDERR("Access type not available for %s: %s",
8819		       s, snd_strerror(err));
8820		return err;
8821	}
8822	/* set the sample format */
8823	err = snd_pcm_hw_params_set_format(pcm, &params, format);
8824	if (err < 0) {
8825		SNDERR("Sample format not available for %s: %s",
8826		       s, snd_strerror(err));
8827		return err;
8828	}
8829	/* set the count of channels */
8830	err = snd_pcm_hw_params_set_channels(pcm, &params, channels);
8831	if (err < 0) {
8832		SNDERR("Channels count (%i) not available for %s: %s",
8833		       channels, s, snd_strerror(err));
8834		return err;
8835	}
8836	/* set the stream rate */
8837	rrate = rate;
8838	err = INTERNAL(snd_pcm_hw_params_set_rate_near)(pcm, &params, &rrate,
8839							0);
8840	if (err < 0) {
8841		SNDERR("Rate %iHz not available for playback: %s",
8842		       rate, snd_strerror(err));
8843		return err;
8844	}
8845	if (rrate != rate) {
8846		SNDERR("Rate doesn't match (requested %iHz, get %iHz)",
8847		       rate, rrate);
8848		return -EINVAL;
8849	}
8850	/* set the buffer time */
8851	params_saved = params;
8852	err = INTERNAL(snd_pcm_hw_params_set_buffer_time_near)(pcm, &params,
8853							&latency, NULL);
8854	if (err < 0) {
8855		/* error path -> set period size as first */
8856		params = params_saved;
8857		/* set the period time */
8858		period_time = latency / 4;
8859		err = INTERNAL(snd_pcm_hw_params_set_period_time_near)(pcm,
8860						&params, &period_time, NULL);
8861		if (err < 0) {
8862			SNDERR("Unable to set period time %i for %s: %s",
8863			       period_time, s, snd_strerror(err));
8864			return err;
8865		}
8866		err = INTERNAL(snd_pcm_hw_params_get_period_size)(&params,
8867							&period_size, NULL);
8868		if (err < 0) {
8869			SNDERR("Unable to get period size for %s: %s",
8870							s, snd_strerror(err));
8871			return err;
8872		}
8873		buffer_size = period_size * 4;
8874		err = INTERNAL(snd_pcm_hw_params_set_buffer_size_near)(pcm,
8875							&params, &buffer_size);
8876		if (err < 0) {
8877			SNDERR("Unable to set buffer size %lu %s: %s",
8878					buffer_size, s, snd_strerror(err));
8879			return err;
8880		}
8881		err = INTERNAL(snd_pcm_hw_params_get_buffer_size)(&params,
8882								&buffer_size);
8883		if (err < 0) {
8884			SNDERR("Unable to get buffer size for %s: %s",
8885			       s, snd_strerror(err));
8886			return err;
8887		}
8888	} else {
8889		/* standard configuration buffer_time -> periods */
8890		err = INTERNAL(snd_pcm_hw_params_get_buffer_size)(&params,
8891								&buffer_size);
8892		if (err < 0) {
8893			SNDERR("Unable to get buffer size for %s: %s",
8894							s, snd_strerror(err));
8895			return err;
8896		}
8897		err = INTERNAL(snd_pcm_hw_params_get_buffer_time)(&params,
8898							&latency, NULL);
8899		if (err < 0) {
8900			SNDERR("Unable to get buffer time (latency) for %s: %s",
8901			       s, snd_strerror(err));
8902			return err;
8903		}
8904		/* set the period time */
8905		period_time = latency / 4;
8906		err = INTERNAL(snd_pcm_hw_params_set_period_time_near)(pcm,
8907						&params, &period_time, NULL);
8908		if (err < 0) {
8909			SNDERR("Unable to set period time %i for %s: %s",
8910			       period_time, s, snd_strerror(err));
8911			return err;
8912		}
8913		err = INTERNAL(snd_pcm_hw_params_get_period_size)(&params,
8914							&period_size, NULL);
8915		if (err < 0) {
8916			SNDERR("Unable to get period size for %s: %s",
8917			       s, snd_strerror(err));
8918			return err;
8919		}
8920	}
8921	/* write the parameters to device */
8922	err = snd_pcm_hw_params(pcm, &params);
8923	if (err < 0) {
8924		SNDERR("Unable to set hw params for %s: %s",
8925		       s, snd_strerror(err));
8926		return err;
8927	}
8928
8929	/* get the current swparams */
8930	err = snd_pcm_sw_params_current(pcm, &swparams);
8931	if (err < 0) {
8932		SNDERR("Unable to determine current swparams for %s: %s",
8933		       s, snd_strerror(err));
8934		return err;
8935	}
8936	/*
8937	 * start the transfer when the buffer is almost full:
8938	 * (buffer_size / avail_min) * avail_min
8939	 */
8940	err = snd_pcm_sw_params_set_start_threshold(pcm, &swparams,
8941				(buffer_size / period_size) * period_size);
8942	if (err < 0) {
8943		SNDERR("Unable to set start threshold mode for %s: %s",
8944		       s, snd_strerror(err));
8945		return err;
8946	}
8947	/*
8948	 * allow the transfer when at least period_size samples can be
8949	 * processed
8950	 */
8951	err = snd_pcm_sw_params_set_avail_min(pcm, &swparams, period_size);
8952	if (err < 0) {
8953		SNDERR("Unable to set avail min for %s: %s",
8954		       s, snd_strerror(err));
8955		return err;
8956	}
8957	/* write the parameters to the playback device */
8958	err = snd_pcm_sw_params(pcm, &swparams);
8959	if (err < 0) {
8960		SNDERR("Unable to set sw params for %s: %s",
8961		       s, snd_strerror(err));
8962		return err;
8963	}
8964	return 0;
8965}
8966
8967/**
8968 * \brief Get the transfer size parameters in a simple way
8969 * \param pcm PCM handle
8970 * \param buffer_size PCM ring buffer size in frames
8971 * \param period_size PCM period size in frames
8972 * \return 0 on success otherwise a negative error code
8973 */
8974int snd_pcm_get_params(snd_pcm_t *pcm,
8975                       snd_pcm_uframes_t *buffer_size,
8976                       snd_pcm_uframes_t *period_size)
8977{
8978	snd_pcm_hw_params_t params = {0};
8979	int err;
8980
8981	assert(pcm);
8982	err = snd_pcm_hw_params_current(pcm, &params);
8983	if (err < 0)
8984	        return err;
8985	err = INTERNAL(snd_pcm_hw_params_get_buffer_size)(&params, buffer_size);
8986	if (err < 0)
8987		return err;
8988	return INTERNAL(snd_pcm_hw_params_get_period_size)(&params, period_size,
8989							   NULL);
8990}
8991