21 #include "../../SDL_internal.h"
23 #if SDL_AUDIO_DRIVER_NAS
33 #include "../SDL_audio_c.h"
36 static void (*NAS_AuCloseServer) (AuServer *);
37 static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
38 static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
39 static void (*NAS_AuHandleEvents) (AuServer *);
40 static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
41 static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
42 static void (*NAS_AuSetElements)
43 (AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
44 static void (*NAS_AuWriteElement)
45 (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
46 static AuUint32 (*NAS_AuReadElement)
47 (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuStatus *);
48 static AuServer *(*NAS_AuOpenServer)
49 (_AuConst
char *, int, _AuConst
char *, int, _AuConst
char *,
char **);
50 static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
51 (AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer);
54 #ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
56 static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC;
57 static void *nas_handle =
NULL;
60 load_nas_sym(
const char *fn,
void **
addr)
70 #define SDL_NAS_SYM(x) \
71 if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1
73 #define SDL_NAS_SYM(x) NAS_##x = x
79 SDL_NAS_SYM(AuCloseServer);
80 SDL_NAS_SYM(AuNextEvent);
81 SDL_NAS_SYM(AuDispatchEvent);
82 SDL_NAS_SYM(AuHandleEvents);
83 SDL_NAS_SYM(AuCreateFlow);
84 SDL_NAS_SYM(AuStartFlow);
85 SDL_NAS_SYM(AuSetElements);
86 SDL_NAS_SYM(AuWriteElement);
87 SDL_NAS_SYM(AuReadElement);
88 SDL_NAS_SYM(AuOpenServer);
89 SDL_NAS_SYM(AuRegisterEventHandler);
95 #ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
98 UnloadNASLibrary(
void)
100 if (nas_handle !=
NULL) {
110 if (nas_handle ==
NULL) {
112 if (nas_handle ==
NULL) {
116 char *err = (
char *) alloca(
len);
134 UnloadNASLibrary(
void)
149 NAS_WaitDevice(
_THIS)
151 while (this->hidden->buf_free < this->hidden->mixlen) {
153 NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
154 NAS_AuDispatchEvent(this->hidden->aud, &ev);
159 NAS_PlayDevice(
_THIS)
161 while (this->hidden->mixlen > this->hidden->buf_free) {
168 NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
169 NAS_AuDispatchEvent(this->hidden->aud, &ev);
171 this->hidden->buf_free -= this->hidden->mixlen;
174 NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
175 this->hidden->mixlen, this->hidden->mixbuf, AuFalse,
178 this->hidden->written += this->hidden->mixlen;
181 fprintf(stderr,
"Wrote %d bytes of audio data\n", this->hidden->mixlen);
186 NAS_GetDeviceBuf(
_THIS)
188 return (this->hidden->mixbuf);
192 NAS_CaptureFromDevice(
_THIS,
void *
buffer,
int buflen)
199 NAS_AuHandleEvents(
h->aud);
214 NAS_FlushCapture(
_THIS)
223 NAS_AuHandleEvents(
h->aud);
224 br = NAS_AuReadElement(
h->aud,
h->flow, 1, sizeof (
buf),
buf,
NULL);
227 }
while ((br ==
sizeof (
buf)) && (total < this->
spec.
size));
231 NAS_CloseDevice(
_THIS)
233 if (this->hidden->aud) {
234 NAS_AuCloseServer(this->hidden->aud);
241 sdlformat_to_auformat(
unsigned int fmt)
245 return AuFormatLinearUnsigned8;
247 return AuFormatLinearSigned8;
249 return AuFormatLinearUnsigned16LSB;
251 return AuFormatLinearUnsigned16MSB;
253 return AuFormatLinearSigned16LSB;
255 return AuFormatLinearSigned16MSB;
261 event_handler(AuServer *
aud, AuEvent * ev, AuEventHandlerRec * hnd)
270 case AuEventTypeElementNotify:
272 AuElementNotifyEvent *
event = (AuElementNotifyEvent *) ev;
274 switch (
event->kind) {
275 case AuElementNotifyKindLowWater:
276 if (
h->buf_free >= 0) {
278 gettimeofday(&
h->last_tv, 0);
279 h->buf_free +=
event->num_bytes;
281 h->buf_free =
event->num_bytes;
284 case AuElementNotifyKindState:
285 switch (
event->cur_state) {
287 if (
event->reason != AuReasonUser) {
288 if (
h->buf_free >= 0) {
289 h->really +=
event->num_bytes;
290 gettimeofday(&
h->last_tv, 0);
291 h->buf_free +=
event->num_bytes;
293 h->buf_free =
event->num_bytes;
309 const unsigned int devicekind = this->
iscapture ? AuComponentKindPhysicalInput : AuComponentKindPhysicalOutput;
310 const int numdevs = AuServerNumDevices(
h->aud);
315 for (i = 0;
i < numdevs;
i++) {
316 const AuDeviceAttributes *
dev = AuServerDevice(
h->aud,
i);
317 if ((AuDeviceKind(
dev) == devicekind) && (AuDeviceNumTracks(
dev) == nch)) {
318 return AuDeviceIdentifier(
dev);
323 for (
i = 0;
i < numdevs;
i++) {
324 const AuDeviceAttributes *
dev = AuServerDevice(
h->aud,
i);
325 if (AuDeviceKind(
dev) == devicekind) {
327 return AuDeviceIdentifier(
dev);
343 if (this->hidden ==
NULL) {
351 !format && test_format;) {
352 format = sdlformat_to_auformat(test_format);
358 return SDL_SetError(
"NAS: Couldn't find any hardware audio formats");
362 this->hidden->aud = NAS_AuOpenServer(
"", 0,
NULL, 0,
NULL,
NULL);
363 if (this->hidden->aud == 0) {
364 return SDL_SetError(
"NAS: Couldn't open connection to NAS server");
367 this->hidden->dev = find_device(
this);
368 if ((this->hidden->dev == AuNone)
369 || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
370 return SDL_SetError(
"NAS: Couldn't find a fitting device on NAS server");
374 if (buffer_size < 4096)
377 if (buffer_size > 32768)
384 AuMakeElementImportDevice(elms, this->
spec.
freq, this->hidden->dev,
385 AuUnlimitedSamples, 0,
NULL);
386 AuMakeElementExportClient(elms + 1, 0, this->
spec.
freq, format,
387 this->spec.channels, AuTrue, buffer_size,
388 buffer_size, 0,
NULL);
390 AuMakeElementImportClient(elms, this->
spec.
freq, format,
391 this->spec.channels, AuTrue, buffer_size,
392 buffer_size / 4, 0,
NULL);
393 AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
394 AuUnlimitedSamples, 0,
NULL);
397 NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue,
400 NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
401 this->hidden->flow, event_handler,
404 NAS_AuStartFlow(this->hidden->aud, this->hidden->flow,
NULL);
408 this->hidden->mixlen = this->
spec.
size;
410 if (this->hidden->mixbuf ==
NULL) {
413 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
421 NAS_Deinitialize(
void)
429 if (LoadNASLibrary() < 0) {
434 SDL_SetError(
"NAS: AuOpenServer() failed (no audio server?)");
437 NAS_AuCloseServer(
aud);
458 "nas",
"Network Audio System", NAS_Init, 0