comparison src/audio/nas/SDL_nasaudio.c @ 3821:18393b045759 SDL-ryan-multiple-audio-device

Moved NAS audio driver to 1.3 API.
author Ryan C. Gordon <icculus@icculus.org>
date Sat, 07 Oct 2006 05:56:59 +0000
parents 7852b5b78af5
children 748707e2ddd1
comparison
equal deleted inserted replaced
3820:1f156fd874fa 3821:18393b045759
34 #include "SDL_audio.h" 34 #include "SDL_audio.h"
35 #include "../SDL_audiomem.h" 35 #include "../SDL_audiomem.h"
36 #include "../SDL_audio_c.h" 36 #include "../SDL_audio_c.h"
37 #include "SDL_nasaudio.h" 37 #include "SDL_nasaudio.h"
38 38
39 /* The tag name used by artsc audio */ 39 /* The tag name used by nas audio */
40 #define NAS_DRIVER_NAME "nas" 40 #define NAS_DRIVER_NAME "nas"
41 41
42 static struct SDL_PrivateAudioData *this2 = NULL; 42 static struct SDL_PrivateAudioData *this2 = NULL;
43 43
44 /* Audio driver functions */ 44 /* !!! FIXME: dynamic loading? */
45 static int NAS_OpenAudio(_THIS, SDL_AudioSpec * spec);
46 static void NAS_WaitAudio(_THIS);
47 static void NAS_PlayAudio(_THIS);
48 static Uint8 *NAS_GetAudioBuf(_THIS);
49 static void NAS_CloseAudio(_THIS);
50
51 /* Audio driver bootstrap functions */
52 45
53 static int 46 static int
54 Audio_Available(void) 47 NAS_Available(void)
55 { 48 {
56 AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL); 49 AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
57 if (!aud) 50 if (!aud)
58 return 0; 51 return 0;
59 52
60 AuCloseServer(aud); 53 AuCloseServer(aud);
61 return 1; 54 return 1;
62 } 55 }
63 56
64 static void
65 Audio_DeleteDevice(SDL_AudioDevice * device)
66 {
67 SDL_free(device->hidden);
68 SDL_free(device);
69 }
70
71 static SDL_AudioDevice *
72 Audio_CreateDevice(int devindex)
73 {
74 SDL_AudioDevice *this;
75
76 /* Initialize all variables that we clean on shutdown */
77 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
78 if (this) {
79 SDL_memset(this, 0, (sizeof *this));
80 this->hidden = (struct SDL_PrivateAudioData *)
81 SDL_malloc((sizeof *this->hidden));
82 }
83 if ((this == NULL) || (this->hidden == NULL)) {
84 SDL_OutOfMemory();
85 if (this) {
86 SDL_free(this);
87 }
88 return (0);
89 }
90 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
91
92 /* Set the function pointers */
93 this->OpenAudio = NAS_OpenAudio;
94 this->WaitAudio = NAS_WaitAudio;
95 this->PlayAudio = NAS_PlayAudio;
96 this->GetAudioBuf = NAS_GetAudioBuf;
97 this->CloseAudio = NAS_CloseAudio;
98
99 this->free = Audio_DeleteDevice;
100
101 return this;
102 }
103
104 AudioBootStrap NAS_bootstrap = {
105 NAS_DRIVER_NAME, "Network Audio System",
106 Audio_Available, Audio_CreateDevice, 0
107 };
108
109 /* This function waits until it is possible to write a full sound buffer */ 57 /* This function waits until it is possible to write a full sound buffer */
110 static void 58 static void
111 NAS_WaitAudio(_THIS) 59 NAS_WaitDevice(_THIS)
112 { 60 {
113 while (this->hidden->buf_free < this->hidden->mixlen) { 61 while (this->hidden->buf_free < this->hidden->mixlen) {
114 AuEvent ev; 62 AuEvent ev;
115 AuNextEvent(this->hidden->aud, AuTrue, &ev); 63 AuNextEvent(this->hidden->aud, AuTrue, &ev);
116 AuDispatchEvent(this->hidden->aud, &ev); 64 AuDispatchEvent(this->hidden->aud, &ev);
117 } 65 }
118 } 66 }
119 67
120 static void 68 static void
121 NAS_PlayAudio(_THIS) 69 NAS_PlayDevice(_THIS)
122 { 70 {
123 while (this->hidden->mixlen > this->hidden->buf_free) { /* We think the buffer is full? Yikes! Ask the server for events, 71 while (this->hidden->mixlen > this->hidden->buf_free) {
124 in the hope that some of them is LowWater events telling us more 72 /*
125 of the buffer is free now than what we think. */ 73 * We think the buffer is full? Yikes! Ask the server for events,
74 * in the hope that some of them is LowWater events telling us more
75 * of the buffer is free now than what we think.
76 */
126 AuEvent ev; 77 AuEvent ev;
127 AuNextEvent(this->hidden->aud, AuTrue, &ev); 78 AuNextEvent(this->hidden->aud, AuTrue, &ev);
128 AuDispatchEvent(this->hidden->aud, &ev); 79 AuDispatchEvent(this->hidden->aud, &ev);
129 } 80 }
130 this->hidden->buf_free -= this->hidden->mixlen; 81 this->hidden->buf_free -= this->hidden->mixlen;
139 fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen); 90 fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
140 #endif 91 #endif
141 } 92 }
142 93
143 static Uint8 * 94 static Uint8 *
144 NAS_GetAudioBuf(_THIS) 95 NAS_GetDeviceBuf(_THIS)
145 { 96 {
146 return (this->hidden->mixbuf); 97 return (this->hidden->mixbuf);
147 } 98 }
148 99
149 static void 100 static void
150 NAS_CloseAudio(_THIS) 101 NAS_CloseDevice(_THIS)
151 { 102 {
152 if (this->hidden->mixbuf != NULL) { 103 if (this->hidden != NULL) {
153 SDL_FreeAudioMem(this->hidden->mixbuf); 104 if (this->hidden->mixbuf != NULL) {
154 this->hidden->mixbuf = NULL; 105 SDL_FreeAudioMem(this->hidden->mixbuf);
155 } 106 this->hidden->mixbuf = NULL;
156 if (this->hidden->aud) { 107 }
157 AuCloseServer(this->hidden->aud); 108 if (this->hidden->aud) {
158 this->hidden->aud = 0; 109 AuCloseServer(this->hidden->aud);
110 this->hidden->aud = 0;
111 }
112 SDL_free(this->hidden);
113 this->hidden = NULL;
159 } 114 }
160 } 115 }
161 116
162 static unsigned char 117 static unsigned char
163 sdlformat_to_auformat(unsigned int fmt) 118 sdlformat_to_auformat(unsigned int fmt)
230 } 185 }
231 return AuNone; 186 return AuNone;
232 } 187 }
233 188
234 static int 189 static int
235 NAS_OpenAudio(_THIS, SDL_AudioSpec * spec) 190 NAS_OpenDevice(_THIS, const char *devname, int iscapture)
236 { 191 {
237 AuElement elms[3]; 192 AuElement elms[3];
238 int buffer_size; 193 int buffer_size;
239 SDL_AudioFormat test_format, format; 194 SDL_AudioFormat test_format, format;
240 195
241 this->hidden->mixbuf = NULL; 196 /* Initialize all variables that we clean on shutdown */
197 this->hidden = (struct SDL_PrivateAudioData *)
198 SDL_malloc((sizeof *this->hidden));
199 if (this->hidden == NULL) {
200 SDL_OutOfMemory();
201 return 0;
202 }
203 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
242 204
243 /* Try for a closest match on audio format */ 205 /* Try for a closest match on audio format */
244 format = 0; 206 format = 0;
245 for (test_format = SDL_FirstAudioFormat(spec->format); 207 for (test_format = SDL_FirstAudioFormat(this->spec.format);
246 !format && test_format;) { 208 !format && test_format;) {
247 format = sdlformat_to_auformat(test_format); 209 format = sdlformat_to_auformat(test_format);
248
249 if (format == AuNone) { 210 if (format == AuNone) {
250 test_format = SDL_NextAudioFormat(); 211 test_format = SDL_NextAudioFormat();
251 } 212 }
252 } 213 }
253 if (format == 0) { 214 if (format == 0) {
254 SDL_SetError("Couldn't find any hardware audio formats"); 215 NAS_CloseDevice(this);
255 return (-1); 216 SDL_SetError("NAS: Couldn't find any hardware audio formats");
256 } 217 return 0;
257 spec->format = test_format; 218 }
219 this->spec.format = test_format;
258 220
259 this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL); 221 this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
260 if (this->hidden->aud == 0) { 222 if (this->hidden->aud == 0) {
261 SDL_SetError("Couldn't open connection to NAS server"); 223 NAS_CloseDevice(this);
262 return (-1); 224 SDL_SetError("NAS: Couldn't open connection to NAS server");
263 } 225 return 0;
264 226 }
265 this->hidden->dev = find_device(this, spec->channels); 227
228 this->hidden->dev = find_device(this, this->spec.channels);
266 if ((this->hidden->dev == AuNone) 229 if ((this->hidden->dev == AuNone)
267 || (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) { 230 || (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) {
268 AuCloseServer(this->hidden->aud); 231 NAS_CloseDevice(this);
269 this->hidden->aud = 0; 232 SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
270 SDL_SetError("Couldn't find a fitting playback device on NAS server"); 233 return 0;
271 return (-1); 234 }
272 } 235
273 236 buffer_size = this->spec.freq;
274 buffer_size = spec->freq;
275 if (buffer_size < 4096) 237 if (buffer_size < 4096)
276 buffer_size = 4096; 238 buffer_size = 4096;
277 239
278 if (buffer_size > 32768) 240 if (buffer_size > 32768)
279 buffer_size = 32768; /* So that the buffer won't get unmanageably big. */ 241 buffer_size = 32768; /* So that the buffer won't get unmanageably big. */
280 242
281 /* Calculate the final parameters for this audio specification */ 243 /* Calculate the final parameters for this audio specification */
282 SDL_CalculateAudioSpec(spec); 244 SDL_CalculateAudioSpec(&this->spec);
283 245
284 this2 = this->hidden; 246 this2 = this->hidden;
285 247
286 AuMakeElementImportClient(elms, spec->freq, format, spec->channels, 248 AuMakeElementImportClient(elms,this->spec.freq,format,this->spec.channels,
287 AuTrue, buffer_size, buffer_size / 4, 0, NULL); 249 AuTrue, buffer_size, buffer_size / 4, 0, NULL);
288 AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, spec->freq, 250 AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
289 AuUnlimitedSamples, 0, NULL); 251 AuUnlimitedSamples, 0, NULL);
290 AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, 252 AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, NULL);
291 NULL);
292 AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0, 253 AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
293 this->hidden->flow, event_handler, 254 this->hidden->flow, event_handler,
294 (AuPointer) NULL); 255 (AuPointer) NULL);
295 256
296 AuStartFlow(this->hidden->aud, this->hidden->flow, NULL); 257 AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
297 258
298 /* Allocate mixing buffer */ 259 /* Allocate mixing buffer */
299 this->hidden->mixlen = spec->size; 260 this->hidden->mixlen = this->spec.size;
300 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); 261 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
301 if (this->hidden->mixbuf == NULL) { 262 if (this->hidden->mixbuf == NULL) {
263 NAS_CloseDevice(this);
264 SDL_OutOfMemory();
302 return (-1); 265 return (-1);
303 } 266 }
304 SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); 267 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
305
306 /* Get the parent process id (we're the parent of the audio thread) */
307 this->hidden->parent = getpid();
308 268
309 /* We're ready to rock and roll. :-) */ 269 /* We're ready to rock and roll. :-) */
310 return (0); 270 return 1;
311 } 271 }
272
273 static int
274 NAS_Init(SDL_AudioDriverImpl *impl)
275 {
276 /* Set the function pointers */
277 impl->OpenDevice = NAS_OpenDevice;
278 impl->PlayDevice = NAS_PlayDevice;
279 impl->WaitDevice = NAS_WaitDevice;
280 impl->GetDeviceBuf = NAS_GetDeviceBuf;
281 impl->CloseDevice = NAS_CloseDevice;
282 impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: is this true? */
283
284 return 1;
285 }
286
287 AudioBootStrap NAS_bootstrap = {
288 NAS_DRIVER_NAME, "Network Audio System",
289 NAS_Available, NAS_Init, 0
290 };
312 291
313 /* vi: set ts=4 sw=4 expandtab: */ 292 /* vi: set ts=4 sw=4 expandtab: */