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