SDL 2.0
SDL_qsa_audio.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22/*
23 * !!! FIXME: streamline this a little by removing all the
24 * !!! FIXME: if (capture) {} else {} sections that are identical
25 * !!! FIXME: except for one flag.
26 */
27
28/* !!! FIXME: can this target support hotplugging? */
29/* !!! FIXME: ...does SDL2 even support QNX? */
30
31#include "../../SDL_internal.h"
32
33#if SDL_AUDIO_DRIVER_QSA
34
35#include <errno.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include <signal.h>
39#include <sys/types.h>
40#include <sys/time.h>
41#include <sched.h>
42#include <sys/select.h>
43#include <sys/neutrino.h>
44#include <sys/asoundlib.h>
45
46#include "SDL_timer.h"
47#include "SDL_audio.h"
48#include "../../core/unix/SDL_poll.h"
49#include "../SDL_audio_c.h"
50#include "SDL_qsa_audio.h"
51
52/* default channel communication parameters */
53#define DEFAULT_CPARAMS_RATE 44100
54#define DEFAULT_CPARAMS_VOICES 1
55
56#define DEFAULT_CPARAMS_FRAG_SIZE 4096
57#define DEFAULT_CPARAMS_FRAGS_MIN 1
58#define DEFAULT_CPARAMS_FRAGS_MAX 1
59
60/* List of found devices */
61#define QSA_MAX_DEVICES 32
62#define QSA_MAX_NAME_LENGTH 81+16 /* Hardcoded in QSA, can't be changed */
63
64typedef struct _QSA_Device
65{
66 char name[QSA_MAX_NAME_LENGTH]; /* Long audio device name for SDL */
67 int cardno;
68 int deviceno;
69} QSA_Device;
70
71QSA_Device qsa_playback_device[QSA_MAX_DEVICES];
72uint32_t qsa_playback_devices;
73
74QSA_Device qsa_capture_device[QSA_MAX_DEVICES];
75uint32_t qsa_capture_devices;
76
77static SDL_INLINE int
78QSA_SetError(const char *fn, int status)
79{
80 return SDL_SetError("QSA: %s() failed: %s", fn, snd_strerror(status));
81}
82
83/* !!! FIXME: does this need to be here? Does the SDL version not work? */
84static void
85QSA_ThreadInit(_THIS)
86{
87 /* Increase default 10 priority to 25 to avoid jerky sound */
88 struct sched_param param;
89 if (SchedGet(0, 0, &param) != -1) {
90 param.sched_priority = param.sched_curpriority + 15;
91 SchedSet(0, 0, SCHED_NOCHANGE, &param);
92 }
93}
94
95/* PCM channel parameters initialize function */
96static void
97QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
98{
99 SDL_zerop(cpars);
100 cpars->channel = SND_PCM_CHANNEL_PLAYBACK;
101 cpars->mode = SND_PCM_MODE_BLOCK;
102 cpars->start_mode = SND_PCM_START_DATA;
103 cpars->stop_mode = SND_PCM_STOP_STOP;
104 cpars->format.format = SND_PCM_SFMT_S16_LE;
105 cpars->format.interleave = 1;
106 cpars->format.rate = DEFAULT_CPARAMS_RATE;
107 cpars->format.voices = DEFAULT_CPARAMS_VOICES;
108 cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE;
109 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN;
110 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX;
111}
112
113/* This function waits until it is possible to write a full sound buffer */
114static void
115QSA_WaitDevice(_THIS)
116{
117 int result;
118
119 /* Setup timeout for playing one fragment equal to 2 seconds */
120 /* If timeout occured than something wrong with hardware or driver */
121 /* For example, Vortex 8820 audio driver stucks on second DAC because */
122 /* it doesn't exist ! */
123 result = SDL_IOReady(this->hidden->audio_fd, !this->hidden->iscapture, 2 * 1000);
124 switch (result) {
125 case -1:
126 SDL_SetError("QSA: SDL_IOReady() failed: %s", strerror(errno));
127 break;
128 case 0:
129 SDL_SetError("QSA: timeout on buffer waiting occured");
130 this->hidden->timeout_on_wait = 1;
131 break;
132 default:
133 this->hidden->timeout_on_wait = 0;
134 break;
135 }
136}
137
138static void
139QSA_PlayDevice(_THIS)
140{
141 snd_pcm_channel_status_t cstatus;
142 int written;
143 int status;
144 int towrite;
145 void *pcmbuffer;
146
147 if (!SDL_AtomicGet(&this->enabled) || !this->hidden) {
148 return;
149 }
150
151 towrite = this->spec.size;
152 pcmbuffer = this->hidden->pcm_buf;
153
154 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
155 do {
156 written =
157 snd_pcm_plugin_write(this->hidden->audio_handle, pcmbuffer,
158 towrite);
159 if (written != towrite) {
160 /* Check if samples playback got stuck somewhere in hardware or in */
161 /* the audio device driver */
162 if ((errno == EAGAIN) && (written == 0)) {
163 if (this->hidden->timeout_on_wait != 0) {
164 SDL_SetError("QSA: buffer playback timeout");
165 return;
166 }
167 }
168
169 /* Check for errors or conditions */
170 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
171 /* Let a little CPU time go by and try to write again */
172 SDL_Delay(1);
173
174 /* if we wrote some data */
175 towrite -= written;
176 pcmbuffer += written * this->spec.channels;
177 continue;
178 } else {
179 if ((errno == EINVAL) || (errno == EIO)) {
180 SDL_zero(cstatus);
181 if (!this->hidden->iscapture) {
182 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
183 } else {
184 cstatus.channel = SND_PCM_CHANNEL_CAPTURE;
185 }
186
187 status =
188 snd_pcm_plugin_status(this->hidden->audio_handle,
189 &cstatus);
190 if (status < 0) {
191 QSA_SetError("snd_pcm_plugin_status", status);
192 return;
193 }
194
195 if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
196 (cstatus.status == SND_PCM_STATUS_READY)) {
197 if (!this->hidden->iscapture) {
198 status =
199 snd_pcm_plugin_prepare(this->hidden->
200 audio_handle,
201 SND_PCM_CHANNEL_PLAYBACK);
202 } else {
203 status =
204 snd_pcm_plugin_prepare(this->hidden->
205 audio_handle,
206 SND_PCM_CHANNEL_CAPTURE);
207 }
208 if (status < 0) {
209 QSA_SetError("snd_pcm_plugin_prepare", status);
210 return;
211 }
212 }
213 continue;
214 } else {
215 return;
216 }
217 }
218 } else {
219 /* we wrote all remaining data */
220 towrite -= written;
221 pcmbuffer += written * this->spec.channels;
222 }
223 } while ((towrite > 0) && SDL_AtomicGet(&this->enabled));
224
225 /* If we couldn't write, assume fatal error for now */
226 if (towrite != 0) {
228 }
229}
230
231static Uint8 *
232QSA_GetDeviceBuf(_THIS)
233{
234 return this->hidden->pcm_buf;
235}
236
237static void
238QSA_CloseDevice(_THIS)
239{
240 if (this->hidden->audio_handle != NULL) {
241 if (!this->hidden->iscapture) {
242 /* Finish playing available samples */
243 snd_pcm_plugin_flush(this->hidden->audio_handle,
244 SND_PCM_CHANNEL_PLAYBACK);
245 } else {
246 /* Cancel unread samples during capture */
247 snd_pcm_plugin_flush(this->hidden->audio_handle,
248 SND_PCM_CHANNEL_CAPTURE);
249 }
250 snd_pcm_close(this->hidden->audio_handle);
251 }
252
253 SDL_free(this->hidden->pcm_buf);
254 SDL_free(this->hidden);
255}
256
257static int
258QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
259{
260 const QSA_Device *device = (const QSA_Device *) handle;
261 int status = 0;
262 int format = 0;
263 SDL_AudioFormat test_format = 0;
264 int found = 0;
265 snd_pcm_channel_setup_t csetup;
266 snd_pcm_channel_params_t cparams;
267
268 /* Initialize all variables that we clean on shutdown */
269 this->hidden =
270 (struct SDL_PrivateAudioData *) SDL_calloc(1,
271 (sizeof
272 (struct
274 if (this->hidden == NULL) {
275 return SDL_OutOfMemory();
276 }
277
278 /* Initialize channel transfer parameters to default */
279 QSA_InitAudioParams(&cparams);
280
281 /* Initialize channel direction: capture or playback */
282 this->hidden->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
283
284 if (device != NULL) {
285 /* Open requested audio device */
286 this->hidden->deviceno = device->deviceno;
287 this->hidden->cardno = device->cardno;
288 status = snd_pcm_open(&this->hidden->audio_handle,
289 device->cardno, device->deviceno,
290 iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
291 } else {
292 /* Open system default audio device */
293 status = snd_pcm_open_preferred(&this->hidden->audio_handle,
294 &this->hidden->cardno,
295 &this->hidden->deviceno,
296 iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
297 }
298
299 /* Check if requested device is opened */
300 if (status < 0) {
301 this->hidden->audio_handle = NULL;
302 return QSA_SetError("snd_pcm_open", status);
303 }
304
305 /* Try for a closest match on audio format */
306 format = 0;
307 /* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */
308 found = 0;
309
310 for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) {
311 /* if match found set format to equivalent QSA format */
312 switch (test_format) {
313 case AUDIO_U8:
314 {
315 format = SND_PCM_SFMT_U8;
316 found = 1;
317 }
318 break;
319 case AUDIO_S8:
320 {
321 format = SND_PCM_SFMT_S8;
322 found = 1;
323 }
324 break;
325 case AUDIO_S16LSB:
326 {
327 format = SND_PCM_SFMT_S16_LE;
328 found = 1;
329 }
330 break;
331 case AUDIO_S16MSB:
332 {
333 format = SND_PCM_SFMT_S16_BE;
334 found = 1;
335 }
336 break;
337 case AUDIO_U16LSB:
338 {
339 format = SND_PCM_SFMT_U16_LE;
340 found = 1;
341 }
342 break;
343 case AUDIO_U16MSB:
344 {
345 format = SND_PCM_SFMT_U16_BE;
346 found = 1;
347 }
348 break;
349 case AUDIO_S32LSB:
350 {
351 format = SND_PCM_SFMT_S32_LE;
352 found = 1;
353 }
354 break;
355 case AUDIO_S32MSB:
356 {
357 format = SND_PCM_SFMT_S32_BE;
358 found = 1;
359 }
360 break;
361 case AUDIO_F32LSB:
362 {
363 format = SND_PCM_SFMT_FLOAT_LE;
364 found = 1;
365 }
366 break;
367 case AUDIO_F32MSB:
368 {
369 format = SND_PCM_SFMT_FLOAT_BE;
370 found = 1;
371 }
372 break;
373 default:
374 {
375 break;
376 }
377 }
378
379 if (!found) {
380 test_format = SDL_NextAudioFormat();
381 }
382 }
383
384 /* assumes test_format not 0 on success */
385 if (test_format == 0) {
386 return SDL_SetError("QSA: Couldn't find any hardware audio formats");
387 }
388
389 this->spec.format = test_format;
390
391 /* Set the audio format */
392 cparams.format.format = format;
393
394 /* Set mono/stereo/4ch/6ch/8ch audio */
395 cparams.format.voices = this->spec.channels;
396
397 /* Set rate */
398 cparams.format.rate = this->spec.freq;
399
400 /* Setup the transfer parameters according to cparams */
401 status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
402 if (status < 0) {
403 return QSA_SetError("snd_pcm_plugin_params", status);
404 }
405
406 /* Make sure channel is setup right one last time */
407 SDL_zero(csetup);
408 if (!this->hidden->iscapture) {
409 csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
410 } else {
411 csetup.channel = SND_PCM_CHANNEL_CAPTURE;
412 }
413
414 /* Setup an audio channel */
415 if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
416 return SDL_SetError("QSA: Unable to setup channel");
417 }
418
419 /* Calculate the final parameters for this audio specification */
421
422 this->hidden->pcm_len = this->spec.size;
423
424 if (this->hidden->pcm_len == 0) {
425 this->hidden->pcm_len =
426 csetup.buf.block.frag_size * this->spec.channels *
427 (snd_pcm_format_width(format) / 8);
428 }
429
430 /*
431 * Allocate memory to the audio buffer and initialize with silence
432 * (Note that buffer size must be a multiple of fragment size, so find
433 * closest multiple)
434 */
435 this->hidden->pcm_buf =
436 (Uint8 *) SDL_malloc(this->hidden->pcm_len);
437 if (this->hidden->pcm_buf == NULL) {
438 return SDL_OutOfMemory();
439 }
440 SDL_memset(this->hidden->pcm_buf, this->spec.silence,
441 this->hidden->pcm_len);
442
443 /* get the file descriptor */
444 if (!this->hidden->iscapture) {
445 this->hidden->audio_fd =
446 snd_pcm_file_descriptor(this->hidden->audio_handle,
447 SND_PCM_CHANNEL_PLAYBACK);
448 } else {
449 this->hidden->audio_fd =
450 snd_pcm_file_descriptor(this->hidden->audio_handle,
451 SND_PCM_CHANNEL_CAPTURE);
452 }
453
454 if (this->hidden->audio_fd < 0) {
455 return QSA_SetError("snd_pcm_file_descriptor", status);
456 }
457
458 /* Prepare an audio channel */
459 if (!this->hidden->iscapture) {
460 /* Prepare audio playback */
461 status =
462 snd_pcm_plugin_prepare(this->hidden->audio_handle,
463 SND_PCM_CHANNEL_PLAYBACK);
464 } else {
465 /* Prepare audio capture */
466 status =
467 snd_pcm_plugin_prepare(this->hidden->audio_handle,
468 SND_PCM_CHANNEL_CAPTURE);
469 }
470
471 if (status < 0) {
472 return QSA_SetError("snd_pcm_plugin_prepare", status);
473 }
474
475 /* We're really ready to rock and roll. :-) */
476 return 0;
477}
478
479static void
480QSA_DetectDevices(void)
481{
482 uint32_t it;
483 uint32_t cards;
485 int32_t status;
486
487 /* Detect amount of available devices */
488 /* this value can be changed in the runtime */
489 cards = snd_cards();
490
491 /* If io-audio manager is not running we will get 0 as number */
492 /* of available audio devices */
493 if (cards == 0) {
494 /* We have no any available audio devices */
495 return;
496 }
497
498 /* !!! FIXME: code duplication */
499 /* Find requested devices by type */
500 { /* output devices */
501 /* Playback devices enumeration requested */
502 for (it = 0; it < cards; it++) {
503 devices = 0;
504 do {
505 status =
506 snd_card_get_longname(it,
507 qsa_playback_device
508 [qsa_playback_devices].name,
509 QSA_MAX_NAME_LENGTH);
510 if (status == EOK) {
511 snd_pcm_t *handle;
512
513 /* Add device number to device name */
514 sprintf(qsa_playback_device[qsa_playback_devices].name +
515 SDL_strlen(qsa_playback_device
516 [qsa_playback_devices].name), " d%d",
517 devices);
518
519 /* Store associated card number id */
520 qsa_playback_device[qsa_playback_devices].cardno = it;
521
522 /* Check if this device id could play anything */
523 status =
524 snd_pcm_open(&handle, it, devices,
525 SND_PCM_OPEN_PLAYBACK);
526 if (status == EOK) {
527 qsa_playback_device[qsa_playback_devices].deviceno =
528 devices;
529 status = snd_pcm_close(handle);
530 if (status == EOK) {
531 SDL_AddAudioDevice(SDL_FALSE, qsa_playback_device[qsa_playback_devices].name, &qsa_playback_device[qsa_playback_devices]);
532 qsa_playback_devices++;
533 }
534 } else {
535 /* Check if we got end of devices list */
536 if (status == -ENOENT) {
537 break;
538 }
539 }
540 } else {
541 break;
542 }
543
544 /* Check if we reached maximum devices count */
545 if (qsa_playback_devices >= QSA_MAX_DEVICES) {
546 break;
547 }
548 devices++;
549 } while (1);
550
551 /* Check if we reached maximum devices count */
552 if (qsa_playback_devices >= QSA_MAX_DEVICES) {
553 break;
554 }
555 }
556 }
557
558 { /* capture devices */
559 /* Capture devices enumeration requested */
560 for (it = 0; it < cards; it++) {
561 devices = 0;
562 do {
563 status =
564 snd_card_get_longname(it,
565 qsa_capture_device
566 [qsa_capture_devices].name,
567 QSA_MAX_NAME_LENGTH);
568 if (status == EOK) {
569 snd_pcm_t *handle;
570
571 /* Add device number to device name */
572 sprintf(qsa_capture_device[qsa_capture_devices].name +
573 SDL_strlen(qsa_capture_device
574 [qsa_capture_devices].name), " d%d",
575 devices);
576
577 /* Store associated card number id */
578 qsa_capture_device[qsa_capture_devices].cardno = it;
579
580 /* Check if this device id could play anything */
581 status =
582 snd_pcm_open(&handle, it, devices,
583 SND_PCM_OPEN_CAPTURE);
584 if (status == EOK) {
585 qsa_capture_device[qsa_capture_devices].deviceno =
586 devices;
587 status = snd_pcm_close(handle);
588 if (status == EOK) {
589 SDL_AddAudioDevice(SDL_TRUE, qsa_capture_device[qsa_capture_devices].name, &qsa_capture_device[qsa_capture_devices]);
590 qsa_capture_devices++;
591 }
592 } else {
593 /* Check if we got end of devices list */
594 if (status == -ENOENT) {
595 break;
596 }
597 }
598
599 /* Check if we reached maximum devices count */
600 if (qsa_capture_devices >= QSA_MAX_DEVICES) {
601 break;
602 }
603 } else {
604 break;
605 }
606 devices++;
607 } while (1);
608
609 /* Check if we reached maximum devices count */
610 if (qsa_capture_devices >= QSA_MAX_DEVICES) {
611 break;
612 }
613 }
614 }
615}
616
617static void
618QSA_Deinitialize(void)
619{
620 /* Clear devices array on shutdown */
621 /* !!! FIXME: we zero these on init...any reason to do it here? */
622 SDL_zero(qsa_playback_device);
623 SDL_zero(qsa_capture_device);
624 qsa_playback_devices = 0;
625 qsa_capture_devices = 0;
626}
627
628static int
629QSA_Init(SDL_AudioDriverImpl * impl)
630{
631 /* Clear devices array */
632 SDL_zero(qsa_playback_device);
633 SDL_zero(qsa_capture_device);
634 qsa_playback_devices = 0;
635 qsa_capture_devices = 0;
636
637 /* Set function pointers */
638 /* DeviceLock and DeviceUnlock functions are used default, */
639 /* provided by SDL, which uses pthread_mutex for lock/unlock */
640 impl->DetectDevices = QSA_DetectDevices;
641 impl->OpenDevice = QSA_OpenDevice;
642 impl->ThreadInit = QSA_ThreadInit;
643 impl->WaitDevice = QSA_WaitDevice;
644 impl->PlayDevice = QSA_PlayDevice;
645 impl->GetDeviceBuf = QSA_GetDeviceBuf;
646 impl->CloseDevice = QSA_CloseDevice;
647 impl->Deinitialize = QSA_Deinitialize;
648 impl->LockDevice = NULL;
649 impl->UnlockDevice = NULL;
650
652 impl->SkipMixerLock = 0;
653 impl->HasCaptureSupport = 1;
656
657 return 1; /* this audio target is available. */
658}
659
661 "qsa", "QNX QSA Audio", QSA_Init, 0
662};
663
664#endif /* SDL_AUDIO_DRIVER_QSA */
665
666/* vi: set ts=4 sw=4 expandtab: */
#define _THIS
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
Definition: SDL_audio.c:469
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1668
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1647
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:486
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1659
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
#define AUDIO_U16MSB
Definition: SDL_audio.h:93
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
#define AUDIO_U8
Definition: SDL_audio.h:89
#define AUDIO_S8
Definition: SDL_audio.h:90
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
unsigned int uint32_t
signed int int32_t
#define SDL_SetError
#define SDL_memset
#define SDL_malloc
#define SDL_strlen
#define SDL_free
#define SDL_Delay
#define SDL_AtomicGet
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint64EXT * result
GLfloat param
GLuint const GLchar * name
int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
Definition: SDL_poll.c:38
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
uint8_t Uint8
Definition: SDL_stdinc.h:179
AudioBootStrap QSAAUDIO_bootstrap
#define NULL
Definition: begin_code.h:167
#define SDL_INLINE
Definition: begin_code.h:134
EGLDeviceEXT * devices
Definition: eglext.h:621
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
SDL_AudioSpec spec
Definition: loopwave.c:31
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
void(* DetectDevices)(void)
Definition: SDL_sysaudio.h:67
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:79
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:82
void(* ThreadInit)(_THIS)
Definition: SDL_sysaudio.h:69
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74
Uint32 size
Definition: SDL_audio.h:186
Uint8 channels
Definition: SDL_audio.h:182
SDL_AudioFormat format
Definition: SDL_audio.h:181