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