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