zenilib: zenilib/jni/external/sdl/src/audio/nas/SDL_nasaudio.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_nasaudio.c
Go to the documentation of this file.
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 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 #include "SDL_config.h"
22
23 #if SDL_AUDIO_DRIVER_NAS
24
25 /* Allow access to a raw mixing buffer */
26
27 #include <signal.h>
28 #include <unistd.h>
29
30 #include "SDL_timer.h"
31 #include "SDL_audio.h"
32 #include "SDL_loadso.h"
33 #include "../SDL_audiomem.h"
34 #include "../SDL_audio_c.h"
35 #include "SDL_nasaudio.h"
36
37 static struct SDL_PrivateAudioData *this2 = NULL;
38
39
40 static void (*NAS_AuCloseServer) (AuServer *);
41 static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
42 static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
43 static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
44 static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
45 static void (*NAS_AuSetElements)
46 (AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
47 static void (*NAS_AuWriteElement)
48 (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
49 static AuServer *(*NAS_AuOpenServer)
50 (_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
51 static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
52 (AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer);
53
54
55 #ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
56
57 static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC;
58 static void *nas_handle = NULL;
59
60 static int
61 load_nas_sym(const char *fn, void **addr)
62 {
63 *addr = SDL_LoadFunction(nas_handle, fn);
64 if (*addr == NULL) {
65 return 0;
66 }
67 return 1;
68 }
69
70 /* cast funcs to char* first, to please GCC's strict aliasing rules. */
71 #define SDL_NAS_SYM(x) \
72 if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1
73 #else
74 #define SDL_NAS_SYM(x) NAS_##x = x
75 #endif
76
77 static int
78 load_nas_syms(void)
79 {
80 SDL_NAS_SYM(AuCloseServer);
81 SDL_NAS_SYM(AuNextEvent);
82 SDL_NAS_SYM(AuDispatchEvent);
83 SDL_NAS_SYM(AuCreateFlow);
84 SDL_NAS_SYM(AuStartFlow);
85 SDL_NAS_SYM(AuSetElements);
86 SDL_NAS_SYM(AuWriteElement);
87 SDL_NAS_SYM(AuOpenServer);
88 SDL_NAS_SYM(AuRegisterEventHandler);
89 return 0;
90 }
91
92 #undef SDL_NAS_SYM
93
94 #ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
95
96 static void
97 UnloadNASLibrary(void)
98 {
99 if (nas_handle != NULL) {
100 SDL_UnloadObject(nas_handle);
101 nas_handle = NULL;
102 }
103 }
104
105 static int
106 LoadNASLibrary(void)
107 {
108 int retval = 0;
109 if (nas_handle == NULL) {
110 nas_handle = SDL_LoadObject(nas_library);
111 if (nas_handle == NULL) {
112 /* Copy error string so we can use it in a new SDL_SetError(). */
113 const char *origerr = SDL_GetError();
114 const size_t len = SDL_strlen(origerr) + 1;
115 char *err = (char *) alloca(len);
116 SDL_strlcpy(err, origerr, len);
117 retval = -1;
118 SDL_SetError("NAS: SDL_LoadObject('%s') failed: %s\n",
119 nas_library, err);
120 } else {
121 retval = load_nas_syms();
122 if (retval < 0) {
123 UnloadNASLibrary();
124 }
125 }
126 }
127 return retval;
128 }
129
130 #else
131
132 static void
133 UnloadNASLibrary(void)
134 {
135 }
136
137 static int
138 LoadNASLibrary(void)
139 {
140 load_nas_syms();
141 return 0;
142 }
143
144 #endif /* SDL_AUDIO_DRIVER_NAS_DYNAMIC */
145
146 /* This function waits until it is possible to write a full sound buffer */
147 static void
148 NAS_WaitDevice(_THIS)
149 {
150 while (this->hidden->buf_free < this->hidden->mixlen) {
151 AuEvent ev;
152 NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
153 NAS_AuDispatchEvent(this->hidden->aud, &ev);
154 }
155 }
156
157 static void
158 NAS_PlayDevice(_THIS)
159 {
160 while (this->hidden->mixlen > this->hidden->buf_free) {
161 /*
162 * We think the buffer is full? Yikes! Ask the server for events,
163 * in the hope that some of them is LowWater events telling us more
164 * of the buffer is free now than what we think.
165 */
166 AuEvent ev;
167 NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
168 NAS_AuDispatchEvent(this->hidden->aud, &ev);
169 }
170 this->hidden->buf_free -= this->hidden->mixlen;
171
172 /* Write the audio data */
173 NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
174 this->hidden->mixlen, this->hidden->mixbuf, AuFalse,
175 NULL);
176
177 this->hidden->written += this->hidden->mixlen;
178
179 #ifdef DEBUG_AUDIO
180 fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
181 #endif
182 }
183
184 static Uint8 *
185 NAS_GetDeviceBuf(_THIS)
186 {
187 return (this->hidden->mixbuf);
188 }
189
190 static void
191 NAS_CloseDevice(_THIS)
192 {
193 if (this->hidden != NULL) {
194 SDL_FreeAudioMem(this->hidden->mixbuf);
195 this->hidden->mixbuf = NULL;
196 if (this->hidden->aud) {
197 NAS_AuCloseServer(this->hidden->aud);
198 this->hidden->aud = 0;
199 }
200 SDL_free(this->hidden);
201 this2 = this->hidden = NULL;
202 }
203 }
204
205 static unsigned char
206 sdlformat_to_auformat(unsigned int fmt)
207 {
208 switch (fmt) {
209 case AUDIO_U8:
210 return AuFormatLinearUnsigned8;
211 case AUDIO_S8:
212 return AuFormatLinearSigned8;
213 case AUDIO_U16LSB:
214 return AuFormatLinearUnsigned16LSB;
215 case AUDIO_U16MSB:
216 return AuFormatLinearUnsigned16MSB;
217 case AUDIO_S16LSB:
218 return AuFormatLinearSigned16LSB;
219 case AUDIO_S16MSB:
220 return AuFormatLinearSigned16MSB;
221 }
222 return AuNone;
223 }
224
225 static AuBool
226 event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
227 {
228 switch (ev->type) {
229 case AuEventTypeElementNotify:
230 {
231 AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
232
233 switch (event->kind) {
234 case AuElementNotifyKindLowWater:
235 if (this2->buf_free >= 0) {
236 this2->really += event->num_bytes;
237 gettimeofday(&this2->last_tv, 0);
238 this2->buf_free += event->num_bytes;
239 } else {
240 this2->buf_free = event->num_bytes;
241 }
242 break;
243 case AuElementNotifyKindState:
244 switch (event->cur_state) {
245 case AuStatePause:
246 if (event->reason != AuReasonUser) {
247 if (this2->buf_free >= 0) {
248 this2->really += event->num_bytes;
249 gettimeofday(&this2->last_tv, 0);
250 this2->buf_free += event->num_bytes;
251 } else {
252 this2->buf_free = event->num_bytes;
253 }
254 }
255 break;
256 }
257 }
258 }
259 }
260 return AuTrue;
261 }
262
263 static AuDeviceID
264 find_device(_THIS, int nch)
265 {
266 /* These "Au" things are all macros, not functions... */
267 int i;
268 for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) {
269 if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) ==
270 AuComponentKindPhysicalOutput) &&
271 AuDeviceNumTracks(AuServerDevice(this->hidden->aud, i)) == nch) {
272 return AuDeviceIdentifier(AuServerDevice(this->hidden->aud, i));
273 }
274 }
275 return AuNone;
276 }
277
278 static int
279 NAS_OpenDevice(_THIS, const char *devname, int iscapture)
280 {
281 AuElement elms[3];
282 int buffer_size;
283 SDL_AudioFormat test_format, format;
284
285 /* Initialize all variables that we clean on shutdown */
286 this->hidden = (struct SDL_PrivateAudioData *)
287 SDL_malloc((sizeof *this->hidden));
288 if (this->hidden == NULL) {
289 return SDL_OutOfMemory();
290 }
291 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
292
293 /* Try for a closest match on audio format */
294 format = 0;
295 for (test_format = SDL_FirstAudioFormat(this->spec.format);
296 !format && test_format;) {
297 format = sdlformat_to_auformat(test_format);
298 if (format == AuNone) {
299 test_format = SDL_NextAudioFormat();
300 }
301 }
302 if (format == 0) {
303 NAS_CloseDevice(this);
304 return SDL_SetError("NAS: Couldn't find any hardware audio formats");
305 }
306 this->spec.format = test_format;
307
308 this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
309 if (this->hidden->aud == 0) {
310 NAS_CloseDevice(this);
311 return SDL_SetError("NAS: Couldn't open connection to NAS server");
312 }
313
314 this->hidden->dev = find_device(this, this->spec.channels);
315 if ((this->hidden->dev == AuNone)
316 || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
317 NAS_CloseDevice(this);
318 return SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
319 }
320
321 buffer_size = this->spec.freq;
322 if (buffer_size < 4096)
323 buffer_size = 4096;
324
325 if (buffer_size > 32768)
326 buffer_size = 32768; /* So that the buffer won't get unmanageably big. */
327
328 /* Calculate the final parameters for this audio specification */
329 SDL_CalculateAudioSpec(&this->spec);
330
331 this2 = this->hidden;
332
333 AuMakeElementImportClient(elms, this->spec.freq, format,
334 this->spec.channels, AuTrue, buffer_size,
335 buffer_size / 4, 0, NULL);
336 AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
337 AuUnlimitedSamples, 0, NULL);
338 NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms,
339 NULL);
340 NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
341 this->hidden->flow, event_handler,
342 (AuPointer) NULL);
343
344 NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
345
346 /* Allocate mixing buffer */
347 this->hidden->mixlen = this->spec.size;
348 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
349 if (this->hidden->mixbuf == NULL) {
350 NAS_CloseDevice(this);
351 return SDL_OutOfMemory();
352 }
353 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
354
355 /* We're ready to rock and roll. :-) */
356 return 0;
357 }
358
359 static void
360 NAS_Deinitialize(void)
361 {
362 UnloadNASLibrary();
363 }
364
365 static int
366 NAS_Init(SDL_AudioDriverImpl * impl)
367 {
368 if (LoadNASLibrary() < 0) {
369 return 0;
370 } else {
371 AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
372 if (aud == NULL) {
373 SDL_SetError("NAS: AuOpenServer() failed (no audio server?)");
374 return 0;
375 }
376 NAS_AuCloseServer(aud);
377 }
378
379 /* Set the function pointers */
380 impl->OpenDevice = NAS_OpenDevice;
381 impl->PlayDevice = NAS_PlayDevice;
382 impl->WaitDevice = NAS_WaitDevice;
383 impl->GetDeviceBuf = NAS_GetDeviceBuf;
384 impl->CloseDevice = NAS_CloseDevice;
385 impl->Deinitialize = NAS_Deinitialize;
386 impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: is this true? */
387
388 return 1; /* this audio target is available. */
389 }
390
391 AudioBootStrap NAS_bootstrap = {
392 "nas", "Network Audio System", NAS_Init, 0
393 };
394
395 #endif /* SDL_AUDIO_DRIVER_NAS */
396
397 /* vi: set ts=4 sw=4 expandtab: */
SDL_AudioDriverImpl::CloseDevice
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:45
SDL_FirstAudioFormat
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1226
void
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
SDL_PrivateAudioData::really
int really
Definition: SDL_nasaudio.h:49
SDL_AudioDriverImpl::WaitDevice
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:41
NULL
#define NULL
Definition: ftobjs.h:61
AUDIO_U16LSB
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
addr
GLenum GLvoid * addr
Definition: glew.h:10667
SDL_PrivateAudioData::aud
AuServer * aud
Definition: SDL_nasaudio.h:40
SDL_AudioDriverImpl::GetDeviceBuf
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:43
SDL_FreeAudioMem
#define SDL_FreeAudioMem
Definition: SDL_audiomem.h:24
SDL_free
DECLSPEC void SDLCALL SDL_free(void *mem)
SDL_PrivateAudioData::iscapture
int iscapture
Definition: SDL_qsa_audio.h:37
SDL_AudioFormat
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
len
GLenum GLsizei len
Definition: glew.h:7035
SDL_GetError
DECLSPEC const char *SDLCALL SDL_GetError(void)
Definition: SDL_error.c:204
SDL_AudioDriverImpl::OpenDevice
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:39
SDL_PrivateAudioData
Definition: SDL_alsa_audio.h:33
SDL_config.h
SDL_NextAudioFormat
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1238
SDL_AudioDriverImpl::PlayDevice
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:42
AUDIO_U8
#define AUDIO_U8
Definition: SDL_audio.h:89
AudioBootStrap
Definition: SDL_sysaudio.h:128
SDL_AudioDriverImpl::OnlyHasDefaultOutputDevice
int OnlyHasDefaultOutputDevice
Definition: SDL_sysaudio.h:56
int
int
Definition: SDL_systhread.c:37
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_LoadObject
DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile)
SDL_strlcpy
DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen)
Definition: SDL_string.c:448
SDL_AudioDriverImpl
Definition: SDL_sysaudio.h:36
SDL_memset
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
SDL_UnloadObject
DECLSPEC void SDLCALL SDL_UnloadObject(void *handle)
format
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
SDL_SetError
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
SDL_malloc
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
SDL_CalculateAudioSpec
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1247
SDL_AudioDriverImpl::Deinitialize
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:48
SDL_AllocAudioMem
#define SDL_AllocAudioMem
Definition: SDL_audiomem.h:23
NAS_bootstrap
AudioBootStrap NAS_bootstrap
SDL_strlen
DECLSPEC size_t SDLCALL SDL_strlen(const char *str)
Definition: SDL_string.c:389
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_loadso.h
SDL_PrivateAudioData::buf_free
int buf_free
Definition: SDL_nasaudio.h:52
AUDIO_S16MSB
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
SDL_audio.h
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
AUDIO_S16LSB
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
SDL_nasaudio.h
i
int i
Definition: pngrutil.c:1377
SDL_LoadFunction
DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle, const char *name)
SDL_timer.h
AUDIO_S8
#define AUDIO_S8
Definition: SDL_audio.h:90
SDL_PrivateAudioData::last_tv
struct timeval last_tv
Definition: SDL_nasaudio.h:51
event
cl_event event
Definition: glew.h:3556
AUDIO_U16MSB
#define AUDIO_U16MSB
Definition: SDL_audio.h:93