21#include "../../SDL_internal.h"
23#if SDL_AUDIO_DRIVER_ALSA
25#ifndef SDL_ALSA_NON_BLOCKING
26#define SDL_ALSA_NON_BLOCKING 0
38#include "../SDL_audio_c.h"
41#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
45static int (*ALSA_snd_pcm_open)
46 (snd_pcm_t **,
const char *, snd_pcm_stream_t, int);
47static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm);
48static snd_pcm_sframes_t (*ALSA_snd_pcm_writei)
49 (snd_pcm_t *,
const void *, snd_pcm_uframes_t);
50static snd_pcm_sframes_t (*ALSA_snd_pcm_readi)
51 (snd_pcm_t *,
void *, snd_pcm_uframes_t);
52static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
53static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
54static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
55static const char *(*ALSA_snd_strerror) (int);
56static size_t(*ALSA_snd_pcm_hw_params_sizeof) (
void);
57static size_t(*ALSA_snd_pcm_sw_params_sizeof) (
void);
58static void (*ALSA_snd_pcm_hw_params_copy)
59 (snd_pcm_hw_params_t *,
const snd_pcm_hw_params_t *);
60static int (*ALSA_snd_pcm_hw_params_any) (snd_pcm_t *, snd_pcm_hw_params_t *);
61static int (*ALSA_snd_pcm_hw_params_set_access)
62 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t);
63static int (*ALSA_snd_pcm_hw_params_set_format)
64 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t);
65static int (*ALSA_snd_pcm_hw_params_set_channels)
66 (snd_pcm_t *, snd_pcm_hw_params_t *,
unsigned int);
67static int (*ALSA_snd_pcm_hw_params_get_channels)
68 (
const snd_pcm_hw_params_t *,
unsigned int *);
69static int (*ALSA_snd_pcm_hw_params_set_rate_near)
70 (snd_pcm_t *, snd_pcm_hw_params_t *,
unsigned int *,
int *);
71static int (*ALSA_snd_pcm_hw_params_set_period_size_near)
72 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t *,
int *);
73static int (*ALSA_snd_pcm_hw_params_get_period_size)
74 (
const snd_pcm_hw_params_t *, snd_pcm_uframes_t *,
int *);
75static int (*ALSA_snd_pcm_hw_params_set_periods_min)
76 (snd_pcm_t *, snd_pcm_hw_params_t *,
unsigned int *,
int *);
77static int (*ALSA_snd_pcm_hw_params_set_periods_first)
78 (snd_pcm_t *, snd_pcm_hw_params_t *,
unsigned int *,
int *);
79static int (*ALSA_snd_pcm_hw_params_get_periods)
80 (
const snd_pcm_hw_params_t *,
unsigned int *,
int *);
81static int (*ALSA_snd_pcm_hw_params_set_buffer_size_near)
82 (snd_pcm_t *pcm, snd_pcm_hw_params_t *, snd_pcm_uframes_t *);
83static int (*ALSA_snd_pcm_hw_params_get_buffer_size)
84 (
const snd_pcm_hw_params_t *, snd_pcm_uframes_t *);
85static int (*ALSA_snd_pcm_hw_params) (snd_pcm_t *, snd_pcm_hw_params_t *);
86static int (*ALSA_snd_pcm_sw_params_current) (snd_pcm_t *,
87 snd_pcm_sw_params_t *);
88static int (*ALSA_snd_pcm_sw_params_set_start_threshold)
89 (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
90static int (*ALSA_snd_pcm_sw_params) (snd_pcm_t *, snd_pcm_sw_params_t *);
91static int (*ALSA_snd_pcm_nonblock) (snd_pcm_t *, int);
92static int (*ALSA_snd_pcm_wait)(snd_pcm_t *, int);
93static int (*ALSA_snd_pcm_sw_params_set_avail_min)
94 (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
95static int (*ALSA_snd_pcm_reset)(snd_pcm_t *);
96static int (*ALSA_snd_device_name_hint) (int,
const char *,
void ***);
97static char* (*ALSA_snd_device_name_get_hint) (
const void *,
const char *);
98static int (*ALSA_snd_device_name_free_hint) (
void **);
99static snd_pcm_sframes_t (*ALSA_snd_pcm_avail)(snd_pcm_t *);
100#ifdef SND_CHMAP_API_VERSION
101static snd_pcm_chmap_t* (*ALSA_snd_pcm_get_chmap) (snd_pcm_t *);
102static int (*ALSA_snd_pcm_chmap_print) (
const snd_pcm_chmap_t *
map,
size_t maxlen,
char *
buf);
105#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
106#define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof
107#define snd_pcm_sw_params_sizeof ALSA_snd_pcm_sw_params_sizeof
109static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC;
110static void *alsa_handle =
NULL;
113load_alsa_sym(
const char *fn,
void **
addr)
125#define SDL_ALSA_SYM(x) \
126 if (!load_alsa_sym(#x, (void **) (char *) &ALSA_##x)) return -1
128#define SDL_ALSA_SYM(x) ALSA_##x = x
134 SDL_ALSA_SYM(snd_pcm_open);
135 SDL_ALSA_SYM(snd_pcm_close);
136 SDL_ALSA_SYM(snd_pcm_writei);
137 SDL_ALSA_SYM(snd_pcm_readi);
138 SDL_ALSA_SYM(snd_pcm_recover);
139 SDL_ALSA_SYM(snd_pcm_prepare);
140 SDL_ALSA_SYM(snd_pcm_drain);
141 SDL_ALSA_SYM(snd_strerror);
142 SDL_ALSA_SYM(snd_pcm_hw_params_sizeof);
143 SDL_ALSA_SYM(snd_pcm_sw_params_sizeof);
144 SDL_ALSA_SYM(snd_pcm_hw_params_copy);
145 SDL_ALSA_SYM(snd_pcm_hw_params_any);
146 SDL_ALSA_SYM(snd_pcm_hw_params_set_access);
147 SDL_ALSA_SYM(snd_pcm_hw_params_set_format);
148 SDL_ALSA_SYM(snd_pcm_hw_params_set_channels);
149 SDL_ALSA_SYM(snd_pcm_hw_params_get_channels);
150 SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near);
151 SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near);
152 SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size);
153 SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_min);
154 SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_first);
155 SDL_ALSA_SYM(snd_pcm_hw_params_get_periods);
156 SDL_ALSA_SYM(snd_pcm_hw_params_set_buffer_size_near);
157 SDL_ALSA_SYM(snd_pcm_hw_params_get_buffer_size);
158 SDL_ALSA_SYM(snd_pcm_hw_params);
159 SDL_ALSA_SYM(snd_pcm_sw_params_current);
160 SDL_ALSA_SYM(snd_pcm_sw_params_set_start_threshold);
161 SDL_ALSA_SYM(snd_pcm_sw_params);
162 SDL_ALSA_SYM(snd_pcm_nonblock);
163 SDL_ALSA_SYM(snd_pcm_wait);
164 SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
165 SDL_ALSA_SYM(snd_pcm_reset);
166 SDL_ALSA_SYM(snd_device_name_hint);
167 SDL_ALSA_SYM(snd_device_name_get_hint);
168 SDL_ALSA_SYM(snd_device_name_free_hint);
169 SDL_ALSA_SYM(snd_pcm_avail);
170#ifdef SND_CHMAP_API_VERSION
171 SDL_ALSA_SYM(snd_pcm_get_chmap);
172 SDL_ALSA_SYM(snd_pcm_chmap_print);
180#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
183UnloadALSALibrary(
void)
185 if (alsa_handle !=
NULL) {
195 if (alsa_handle ==
NULL) {
197 if (alsa_handle ==
NULL) {
201 retval = load_alsa_syms();
213UnloadALSALibrary(
void)
232 return (
const char *)
handle;
242 return "plug:surround51";
243 }
else if (channels == 4) {
244 return "plug:surround40";
253ALSA_WaitDevice(
_THIS)
255#if SDL_ALSA_NON_BLOCKING
256 const snd_pcm_sframes_t needed = (snd_pcm_sframes_t) this->
spec.
samples;
258 const snd_pcm_sframes_t rc = ALSA_snd_pcm_avail(this->hidden->pcm_handle);
259 if ((rc < 0) && (rc != -EAGAIN)) {
261 fprintf(stderr,
"ALSA snd_pcm_avail failed (unrecoverable): %s\n",
262 ALSA_snd_strerror(rc));
265 }
else if (rc < needed) {
282#define SWIZ6(T, buf, numframes) \
283 T *ptr = (T *) buf; \
285 for (i = 0; i < numframes; i++, ptr += 6) { \
287 tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \
288 tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \
292swizzle_alsa_channels_6_64bit(
void *
buffer,
Uint32 bufferlen)
298swizzle_alsa_channels_6_32bit(
void *
buffer,
Uint32 bufferlen)
304swizzle_alsa_channels_6_16bit(
void *
buffer,
Uint32 bufferlen)
310swizzle_alsa_channels_6_8bit(
void *
buffer,
Uint32 bufferlen)
327 case 8: swizzle_alsa_channels_6_8bit(
buffer, bufferlen);
break;
328 case 16: swizzle_alsa_channels_6_16bit(
buffer, bufferlen);
break;
329 case 32: swizzle_alsa_channels_6_32bit(
buffer, bufferlen);
break;
330 case 64: swizzle_alsa_channels_6_64bit(
buffer, bufferlen);
break;
331 default:
SDL_assert(!
"unhandled bitsize");
break;
338#ifdef SND_CHMAP_API_VERSION
349ALSA_PlayDevice(
_THIS)
351 const Uint8 *sample_buf = (
const Uint8 *) this->hidden->mixbuf;
354 snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->
spec.
samples);
356 this->hidden->swizzle_func(
this, this->hidden->mixbuf, frames_left);
359 int status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
360 sample_buf, frames_left);
363 if (status == -EAGAIN) {
369 status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
372 fprintf(stderr,
"ALSA write failed (unrecoverable): %s\n",
373 ALSA_snd_strerror(status));
379 else if (status == 0) {
386 sample_buf += status * frame_size;
387 frames_left -= status;
392ALSA_GetDeviceBuf(
_THIS)
394 return (this->hidden->mixbuf);
398ALSA_CaptureFromDevice(
_THIS,
void *
buffer,
int buflen)
403 const int total_frames = buflen / frame_size;
404 snd_pcm_uframes_t frames_left = total_frames;
405 snd_pcm_uframes_t wait_time = frame_size / 2;
412 status = ALSA_snd_pcm_readi(this->hidden->pcm_handle,
413 sample_buf, frames_left);
415 if (status == -EAGAIN) {
416 ALSA_snd_pcm_wait(this->hidden->pcm_handle, wait_time);
419 else if (status < 0) {
421 status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
424 fprintf(stderr,
"ALSA read failed (unrecoverable): %s\n",
425 ALSA_snd_strerror(status));
432 sample_buf += status * frame_size;
433 frames_left -= status;
436 this->hidden->swizzle_func(
this,
buffer, total_frames - frames_left);
438 return (total_frames - frames_left) * frame_size;
442ALSA_FlushCapture(
_THIS)
444 ALSA_snd_pcm_reset(this->hidden->pcm_handle);
448ALSA_CloseDevice(
_THIS)
450 if (this->hidden->pcm_handle) {
457 ALSA_snd_pcm_close(this->hidden->pcm_handle);
464ALSA_set_buffer_size(
_THIS, snd_pcm_hw_params_t *
params)
467 snd_pcm_hw_params_t *hwparams;
468 snd_pcm_uframes_t persize;
469 unsigned int periods;
472 snd_pcm_hw_params_alloca(&hwparams);
473 ALSA_snd_pcm_hw_params_copy(hwparams,
params);
477 status = ALSA_snd_pcm_hw_params_set_period_size_near(
478 this->hidden->pcm_handle, hwparams, &persize,
NULL);
485 status = ALSA_snd_pcm_hw_params_set_periods_min(
486 this->hidden->pcm_handle, hwparams, &periods,
NULL);
491 status = ALSA_snd_pcm_hw_params_set_periods_first(
492 this->hidden->pcm_handle, hwparams, &periods,
NULL);
498 status = ALSA_snd_pcm_hw_params(this->hidden->pcm_handle, hwparams);
509 ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &
bufsize);
512 "ALSA: period size = %ld, periods = %u, buffer size = %lu\n",
520ALSA_OpenDevice(
_THIS,
void *
handle,
const char *devname,
int iscapture)
523 snd_pcm_t *pcm_handle =
NULL;
524 snd_pcm_hw_params_t *hwparams =
NULL;
525 snd_pcm_sw_params_t *swparams =
NULL;
526 snd_pcm_format_t
format = 0;
528 unsigned int rate = 0;
529 unsigned int channels = 0;
530#ifdef SND_CHMAP_API_VERSION
531 snd_pcm_chmap_t *chmap;
538 if (this->hidden ==
NULL) {
547 iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
551 return SDL_SetError(
"ALSA: Couldn't open audio device: %s",
552 ALSA_snd_strerror(status));
558 snd_pcm_hw_params_alloca(&hwparams);
559 status = ALSA_snd_pcm_hw_params_any(
pcm_handle, hwparams);
561 return SDL_SetError(
"ALSA: Couldn't get hardware config: %s",
562 ALSA_snd_strerror(status));
566 status = ALSA_snd_pcm_hw_params_set_access(
pcm_handle, hwparams,
567 SND_PCM_ACCESS_RW_INTERLEAVED);
569 return SDL_SetError(
"ALSA: Couldn't set interleaved access: %s",
570 ALSA_snd_strerror(status));
576 test_format && (status < 0);) {
578 switch (test_format) {
580 format = SND_PCM_FORMAT_U8;
583 format = SND_PCM_FORMAT_S8;
586 format = SND_PCM_FORMAT_S16_LE;
589 format = SND_PCM_FORMAT_S16_BE;
592 format = SND_PCM_FORMAT_U16_LE;
595 format = SND_PCM_FORMAT_U16_BE;
598 format = SND_PCM_FORMAT_S32_LE;
601 format = SND_PCM_FORMAT_S32_BE;
604 format = SND_PCM_FORMAT_FLOAT_LE;
607 format = SND_PCM_FORMAT_FLOAT_BE;
614 status = ALSA_snd_pcm_hw_params_set_format(
pcm_handle,
622 return SDL_SetError(
"ALSA: Couldn't find any hardware audio formats");
629 this->hidden->swizzle_func = swizzle_alsa_channels;
630#ifdef SND_CHMAP_API_VERSION
633 ALSA_snd_pcm_chmap_print(chmap,
sizeof(chmap_str), chmap_str);
634 if (
SDL_strcmp(
"FL FR FC LFE RL RR", chmap_str) == 0 ||
635 SDL_strcmp(
"FL FR FC LFE SL SR", chmap_str) == 0) {
636 this->hidden->swizzle_func = no_swizzle;
643 status = ALSA_snd_pcm_hw_params_set_channels(
pcm_handle, hwparams,
647 status = ALSA_snd_pcm_hw_params_get_channels(hwparams, &channels);
649 return SDL_SetError(
"ALSA: Couldn't set audio channels");
656 status = ALSA_snd_pcm_hw_params_set_rate_near(
pcm_handle, hwparams,
659 return SDL_SetError(
"ALSA: Couldn't set audio frequency: %s",
660 ALSA_snd_strerror(status));
665 status = ALSA_set_buffer_size(
this, hwparams);
667 return SDL_SetError(
"Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
671 snd_pcm_sw_params_alloca(&swparams);
672 status = ALSA_snd_pcm_sw_params_current(
pcm_handle, swparams);
674 return SDL_SetError(
"ALSA: Couldn't get software config: %s",
675 ALSA_snd_strerror(status));
679 return SDL_SetError(
"Couldn't set minimum available samples: %s",
680 ALSA_snd_strerror(status));
683 ALSA_snd_pcm_sw_params_set_start_threshold(
pcm_handle, swparams, 1);
685 return SDL_SetError(
"ALSA: Couldn't set start threshold: %s",
686 ALSA_snd_strerror(status));
688 status = ALSA_snd_pcm_sw_params(
pcm_handle, swparams);
690 return SDL_SetError(
"Couldn't set software audio parameters: %s",
691 ALSA_snd_strerror(status));
699 this->hidden->mixlen = this->
spec.
size;
701 if (this->hidden->mixbuf ==
NULL) {
704 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
707 #if !SDL_ALSA_NON_BLOCKING
717typedef struct ALSA_Device
721 struct ALSA_Device *next;
725add_device(
const int iscapture,
const char *
name,
void *hint, ALSA_Device **pSeen)
727 ALSA_Device *dev =
SDL_malloc(
sizeof (ALSA_Device));
741 desc = ALSA_snd_device_name_get_hint(hint,
"DESC");
747 desc = (
char *)
name;
755 if ((ptr = strchr(desc,
'\n')) !=
NULL) {
774 dev->iscapture = iscapture;
784ALSA_HotplugThread(
void *arg)
786 SDL_sem *first_run_semaphore = (SDL_sem *) arg;
800 if (ALSA_snd_device_name_hint(-1,
"pcm", &hints) == 0) {
802 const char *match =
NULL;
803 int bestmatch = 0xFFFF;
804 size_t match_len = 0;
806 static const char *
const prefixes[] = {
807 "hw:",
"sysdefault:",
"default:",
NULL
816 for (
i = 0; hints[
i];
i++) {
817 char *
name = ALSA_snd_device_name_get_hint(hints[
i],
"NAME");
827 for (
j = 0; prefixes[
j];
j++) {
828 const char *prefix = prefixes[
j];
834 match_len = prefixlen;
843 for (
i = 0; hints[
i];
i++) {
847 if ((!match) && (defaultdev !=
i)) {
851 name = ALSA_snd_device_name_get_hint(hints[
i],
"NAME");
858 char *ioid = ALSA_snd_device_name_get_hint(hints[
i],
"IOID");
866 if (!isoutput && !isinput) {
872 for (dev = unseen; dev; dev = next) {
874 if ( (
SDL_strcmp(dev->name,
name) == 0) && (((isinput) && dev->iscapture) || ((isoutput) && !dev->iscapture)) ) {
883 if (isoutput) have_output =
SDL_TRUE;
889 if (isinput && !have_input) {
892 if (isoutput && !have_output) {
900 ALSA_snd_device_name_free_hint(hints);
905 for (dev = unseen; dev; dev = next) {
915 if (first_run_semaphore) {
917 first_run_semaphore =
NULL;
928 for (dev =
devices; dev; dev = next) {
939ALSA_DetectDevices(
void)
949 ALSA_hotplug_thread =
SDL_CreateThread(ALSA_HotplugThread,
"SDLHotplugALSA", semaphore);
950 if (ALSA_hotplug_thread) {
958ALSA_Deinitialize(
void)
960 if (ALSA_hotplug_thread !=
NULL) {
963 ALSA_hotplug_thread =
NULL;
972 if (LoadALSALibrary() < 0) {
994 "alsa",
"ALSA PCM audio", ALSA_Init, 0
#define SDL_assert(condition)
void SDL_RemoveAudioDevice(const int iscapture, void *handle)
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
SDL_AudioFormat SDL_NextAudioFormat(void)
static SDL_AudioDevice * get_audio_device(SDL_AudioDeviceID id)
Uint16 SDL_AudioFormat
Audio format flags.
#define SDL_AUDIO_BITSIZE(x)
#define SDL_SetThreadPriority
#define SDL_DestroySemaphore
#define SDL_CreateSemaphore
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
#define SDL_OutOfMemory()
const GLubyte GLuint GLuint GLuint GLuint alpha GLboolean GLboolean GLboolean GLboolean alpha GLint GLint GLsizei GLsizei GLenum type GLenum GLint GLenum GLint GLint GLsizei GLsizei GLint border GLenum GLint GLint GLint GLint GLint GLsizei GLsizei height GLsizei GLsizei GLenum GLenum const GLvoid *pixels GLenum GLint GLint GLint GLint j2 GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble zFar GLenum GLenum GLint *params GLenum GLenum GLint *params GLenum GLenum GLint *params GLenum GLenum GLfloat *params GLenum GLint GLenum GLenum GLvoid *pixels GLenum GLint GLenum GLint *params GLenum GLenum GLint *params GLenum GLsizei const GLvoid *pointer GLenum GLenum const GLint *params GLenum GLfloat GLfloat GLint GLint const GLfloat *points GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat *points GLint GLfloat GLfloat GLint GLfloat GLfloat v2 GLenum GLenum const GLint *params GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble zFar GLenum map
void * SDL_LoadFunction(void *handle, const char *name)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint const GLchar * name
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLuint GLsizei bufsize
AudioBootStrap ALSA_bootstrap
@ SDL_THREAD_PRIORITY_LOW
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
EGLImageKHR EGLint EGLint * handle
static SDL_AudioDeviceID device
void(* PlayDevice)(_THIS)
void(* WaitDevice)(_THIS)
void(* CloseDevice)(_THIS)
void(* FlushCapture)(_THIS)
void(* DetectDevices)(void)
void(* Deinitialize)(void)
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Uint8 *(* GetDeviceBuf)(_THIS)
A type representing an atomic integer value. It is a struct so people don't accidentally use numeric ...