SDL  2.0
SDL_qsa_audio.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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 
64 typedef 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 
71 QSA_Device qsa_playback_device[QSA_MAX_DEVICES];
72 uint32_t qsa_playback_devices;
73 
74 QSA_Device qsa_capture_device[QSA_MAX_DEVICES];
75 uint32_t qsa_capture_devices;
76 
77 static SDL_INLINE int
78 QSA_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? */
84 static void
85 QSA_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 */
96 static void
97 QSA_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 */
114 static void
115 QSA_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 
138 static void
139 QSA_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 
231 static Uint8 *
232 QSA_GetDeviceBuf(_THIS)
233 {
234  return this->hidden->pcm_buf;
235 }
236 
237 static void
238 QSA_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 
257 static int
258 QSA_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 
479 static void
480 QSA_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 
617 static void
618 QSA_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 
628 static int
629 QSA_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 
651  impl->ProvidesOwnCallbackThread = 0;
652  impl->SkipMixerLock = 0;
653  impl->HasCaptureSupport = 1;
654  impl->OnlyHasDefaultOutputDevice = 0;
655  impl->OnlyHasDefaultCaptureDevice = 0;
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: */
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1584
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
Definition: SDL_poll.c:38
GLuint64EXT * result
void(* DetectDevices)(void)
Definition: SDL_sysaudio.h:67
signed int int32_t
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:449
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
void(* UnlockDevice)(_THIS)
Definition: SDL_sysaudio.h:81
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1596
GLuint const GLchar * name
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioSpec spec
Definition: loopwave.c:31
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define AUDIO_U8
Definition: SDL_audio.h:89
void(* ThreadInit)(_THIS)
Definition: SDL_sysaudio.h:69
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
Uint8 channels
Definition: SDL_audio.h:181
#define _THIS
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
AudioBootStrap QSAAUDIO_bootstrap
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:83
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1605
void(* LockDevice)(_THIS)
Definition: SDL_sysaudio.h:80
#define SDL_Delay
GLenum GLenum GLsizei const GLuint GLboolean enabled
Uint32 size
Definition: SDL_audio.h:185
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
unsigned int uint32_t
#define SDL_SetError
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:79
#define SDL_calloc
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
#define SDL_strlen
SDL_AudioFormat format
Definition: SDL_audio.h:180
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:75
#define SDL_AtomicGet
#define SDL_INLINE
Definition: begin_code.h:131
#define SDL_malloc
GLfloat param
#define AUDIO_S8
Definition: SDL_audio.h:90
EGLDeviceEXT * devices
Definition: eglext.h:621
#define SDL_memset
#define AUDIO_U16MSB
Definition: SDL_audio.h:93
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
Definition: SDL_audio.c:432