23 #if SDL_AUDIO_DRIVER_NAS
33 #include "../SDL_audiomem.h"
34 #include "../SDL_audio_c.h"
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);
55 #ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
57 static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC;
58 static void *nas_handle =
NULL;
61 load_nas_sym(
const char *fn,
void **
addr)
71 #define SDL_NAS_SYM(x) \
72 if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1
74 #define SDL_NAS_SYM(x) NAS_##x = x
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);
94 #ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
97 UnloadNASLibrary(
void)
99 if (nas_handle !=
NULL) {
109 if (nas_handle ==
NULL) {
111 if (nas_handle ==
NULL) {
115 char *err = (
char *) alloca(len);
121 retval = load_nas_syms();
133 UnloadNASLibrary(
void)
148 NAS_WaitDevice(
_THIS)
150 while (this->hidden->buf_free < this->hidden->mixlen) {
152 NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
153 NAS_AuDispatchEvent(this->hidden->aud, &ev);
158 NAS_PlayDevice(
_THIS)
160 while (this->hidden->mixlen > this->hidden->buf_free) {
167 NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
168 NAS_AuDispatchEvent(this->hidden->aud, &ev);
170 this->hidden->buf_free -= this->hidden->mixlen;
173 NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
174 this->hidden->mixlen, this->hidden->mixbuf, AuFalse,
177 this->hidden->written += this->hidden->mixlen;
180 fprintf(stderr,
"Wrote %d bytes of audio data\n", this->hidden->mixlen);
185 NAS_GetDeviceBuf(
_THIS)
187 return (this->hidden->mixbuf);
191 NAS_CloseDevice(
_THIS)
193 if (this->hidden !=
NULL) {
195 this->hidden->mixbuf =
NULL;
196 if (this->hidden->aud) {
197 NAS_AuCloseServer(this->hidden->aud);
198 this->hidden->aud = 0;
201 this2 = this->hidden =
NULL;
206 sdlformat_to_auformat(
unsigned int fmt)
210 return AuFormatLinearUnsigned8;
212 return AuFormatLinearSigned8;
214 return AuFormatLinearUnsigned16LSB;
216 return AuFormatLinearUnsigned16MSB;
218 return AuFormatLinearSigned16LSB;
220 return AuFormatLinearSigned16MSB;
226 event_handler(AuServer *
aud, AuEvent * ev, AuEventHandlerRec * hnd)
229 case AuEventTypeElementNotify:
231 AuElementNotifyEvent *
event = (AuElementNotifyEvent *) ev;
233 switch (
event->kind) {
234 case AuElementNotifyKindLowWater:
236 this2->
really +=
event->num_bytes;
237 gettimeofday(&this2->
last_tv, 0);
238 this2->
buf_free +=
event->num_bytes;
243 case AuElementNotifyKindState:
244 switch (
event->cur_state) {
246 if (
event->reason != AuReasonUser) {
248 this2->
really +=
event->num_bytes;
249 gettimeofday(&this2->
last_tv, 0);
250 this2->
buf_free +=
event->num_bytes;
264 find_device(
_THIS,
int nch)
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));
288 if (this->hidden ==
NULL) {
291 SDL_memset(this->hidden, 0, (
sizeof *this->hidden));
296 !format && test_format;) {
297 format = sdlformat_to_auformat(test_format);
298 if (format == AuNone) {
303 NAS_CloseDevice(
this);
304 return SDL_SetError(
"NAS: Couldn't find any hardware audio formats");
306 this->spec.format = test_format;
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");
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");
321 buffer_size = this->spec.freq;
322 if (buffer_size < 4096)
325 if (buffer_size > 32768)
331 this2 = this->hidden;
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,
340 NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
341 this->hidden->flow, event_handler,
344 NAS_AuStartFlow(this->hidden->aud, this->hidden->flow,
NULL);
347 this->hidden->mixlen = this->spec.size;
349 if (this->hidden->mixbuf ==
NULL) {
350 NAS_CloseDevice(
this);
353 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
360 NAS_Deinitialize(
void)
368 if (LoadNASLibrary() < 0) {
371 AuServer *aud = NAS_AuOpenServer(
"", 0,
NULL, 0,
NULL,
NULL);
373 SDL_SetError(
"NAS: AuOpenServer() failed (no audio server?)");
376 NAS_AuCloseServer(aud);
392 "nas",
"Network Audio System", NAS_Init, 0
void(* CloseDevice)(_THIS)
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
void(* WaitDevice)(_THIS)
Uint8 *(* GetDeviceBuf)(_THIS)
DECLSPEC void SDLCALL SDL_free(void *mem)
Uint16 SDL_AudioFormat
Audio format flags.
DECLSPEC const char *SDLCALL SDL_GetError(void)
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
SDL_AudioFormat SDL_NextAudioFormat(void)
void(* PlayDevice)(_THIS)
int OnlyHasDefaultOutputDevice
DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile)
DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen)
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
DECLSPEC void SDLCALL SDL_UnloadObject(void *handle)
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
void(* Deinitialize)(void)
#define SDL_AllocAudioMem
AudioBootStrap NAS_bootstrap
DECLSPEC size_t SDLCALL SDL_strlen(const char *str)
#define SDL_OutOfMemory()
uint8_t Uint8
An unsigned 8-bit integer type.
DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle, const char *name)