Mercurial > sdl-ios-xcode
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: */ |