Mercurial > sdl-ios-xcode
comparison src/audio/nas/SDL_nasaudio.c @ 1662:782fd950bd46 SDL-1.3
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.
WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.
The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce
The headers are being converted to automatically generate doxygen documentation.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 28 May 2006 13:04:16 +0000 |
parents | d910939febfa |
children | 4da1ee79c9af |
comparison
equal
deleted
inserted
replaced
1661:281d3f4870e5 | 1662:782fd950bd46 |
---|---|
41 #define NAS_DRIVER_NAME "nas" | 41 #define NAS_DRIVER_NAME "nas" |
42 | 42 |
43 static struct SDL_PrivateAudioData *this2 = NULL; | 43 static struct SDL_PrivateAudioData *this2 = NULL; |
44 | 44 |
45 /* Audio driver functions */ | 45 /* Audio driver functions */ |
46 static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec); | 46 static int NAS_OpenAudio (_THIS, SDL_AudioSpec * spec); |
47 static void NAS_WaitAudio(_THIS); | 47 static void NAS_WaitAudio (_THIS); |
48 static void NAS_PlayAudio(_THIS); | 48 static void NAS_PlayAudio (_THIS); |
49 static Uint8 *NAS_GetAudioBuf(_THIS); | 49 static Uint8 *NAS_GetAudioBuf (_THIS); |
50 static void NAS_CloseAudio(_THIS); | 50 static void NAS_CloseAudio (_THIS); |
51 | 51 |
52 /* Audio driver bootstrap functions */ | 52 /* Audio driver bootstrap functions */ |
53 | 53 |
54 static int Audio_Available(void) | 54 static int |
55 { | 55 Audio_Available (void) |
56 AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL); | 56 { |
57 if (!aud) return 0; | 57 AuServer *aud = AuOpenServer ("", 0, NULL, 0, NULL, NULL); |
58 | 58 if (!aud) |
59 AuCloseServer(aud); | 59 return 0; |
60 return 1; | 60 |
61 } | 61 AuCloseServer (aud); |
62 | 62 return 1; |
63 static void Audio_DeleteDevice(SDL_AudioDevice *device) | 63 } |
64 { | 64 |
65 SDL_free(device->hidden); | 65 static void |
66 SDL_free(device); | 66 Audio_DeleteDevice (SDL_AudioDevice * device) |
67 } | 67 { |
68 | 68 SDL_free (device->hidden); |
69 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | 69 SDL_free (device); |
70 { | 70 } |
71 SDL_AudioDevice *this; | 71 |
72 | 72 static SDL_AudioDevice * |
73 /* Initialize all variables that we clean on shutdown */ | 73 Audio_CreateDevice (int devindex) |
74 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); | 74 { |
75 if ( this ) { | 75 SDL_AudioDevice *this; |
76 SDL_memset(this, 0, (sizeof *this)); | 76 |
77 this->hidden = (struct SDL_PrivateAudioData *) | 77 /* Initialize all variables that we clean on shutdown */ |
78 SDL_malloc((sizeof *this->hidden)); | 78 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice)); |
79 } | 79 if (this) { |
80 if ( (this == NULL) || (this->hidden == NULL) ) { | 80 SDL_memset (this, 0, (sizeof *this)); |
81 SDL_OutOfMemory(); | 81 this->hidden = (struct SDL_PrivateAudioData *) |
82 if ( this ) { | 82 SDL_malloc ((sizeof *this->hidden)); |
83 SDL_free(this); | 83 } |
84 } | 84 if ((this == NULL) || (this->hidden == NULL)) { |
85 return(0); | 85 SDL_OutOfMemory (); |
86 } | 86 if (this) { |
87 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | 87 SDL_free (this); |
88 | 88 } |
89 /* Set the function pointers */ | 89 return (0); |
90 this->OpenAudio = NAS_OpenAudio; | 90 } |
91 this->WaitAudio = NAS_WaitAudio; | 91 SDL_memset (this->hidden, 0, (sizeof *this->hidden)); |
92 this->PlayAudio = NAS_PlayAudio; | 92 |
93 this->GetAudioBuf = NAS_GetAudioBuf; | 93 /* Set the function pointers */ |
94 this->CloseAudio = NAS_CloseAudio; | 94 this->OpenAudio = NAS_OpenAudio; |
95 | 95 this->WaitAudio = NAS_WaitAudio; |
96 this->free = Audio_DeleteDevice; | 96 this->PlayAudio = NAS_PlayAudio; |
97 | 97 this->GetAudioBuf = NAS_GetAudioBuf; |
98 return this; | 98 this->CloseAudio = NAS_CloseAudio; |
99 | |
100 this->free = Audio_DeleteDevice; | |
101 | |
102 return this; | |
99 } | 103 } |
100 | 104 |
101 AudioBootStrap NAS_bootstrap = { | 105 AudioBootStrap NAS_bootstrap = { |
102 NAS_DRIVER_NAME, "Network Audio System", | 106 NAS_DRIVER_NAME, "Network Audio System", |
103 Audio_Available, Audio_CreateDevice | 107 Audio_Available, Audio_CreateDevice |
104 }; | 108 }; |
105 | 109 |
106 /* This function waits until it is possible to write a full sound buffer */ | 110 /* This function waits until it is possible to write a full sound buffer */ |
107 static void NAS_WaitAudio(_THIS) | 111 static void |
108 { | 112 NAS_WaitAudio (_THIS) |
109 while ( this->hidden->buf_free < this->hidden->mixlen ) { | 113 { |
110 AuEvent ev; | 114 while (this->hidden->buf_free < this->hidden->mixlen) { |
111 AuNextEvent(this->hidden->aud, AuTrue, &ev); | 115 AuEvent ev; |
112 AuDispatchEvent(this->hidden->aud, &ev); | 116 AuNextEvent (this->hidden->aud, AuTrue, &ev); |
113 } | 117 AuDispatchEvent (this->hidden->aud, &ev); |
114 } | 118 } |
115 | 119 } |
116 static void NAS_PlayAudio(_THIS) | 120 |
117 { | 121 static void |
118 while (this->hidden->mixlen > this->hidden->buf_free) { /* We think the buffer is full? Yikes! Ask the server for events, | 122 NAS_PlayAudio (_THIS) |
119 in the hope that some of them is LowWater events telling us more | 123 { |
120 of the buffer is free now than what we think. */ | 124 while (this->hidden->mixlen > this->hidden->buf_free) { /* We think the buffer is full? Yikes! Ask the server for events, |
121 AuEvent ev; | 125 in the hope that some of them is LowWater events telling us more |
122 AuNextEvent(this->hidden->aud, AuTrue, &ev); | 126 of the buffer is free now than what we think. */ |
123 AuDispatchEvent(this->hidden->aud, &ev); | 127 AuEvent ev; |
124 } | 128 AuNextEvent (this->hidden->aud, AuTrue, &ev); |
125 this->hidden->buf_free -= this->hidden->mixlen; | 129 AuDispatchEvent (this->hidden->aud, &ev); |
126 | 130 } |
127 /* Write the audio data */ | 131 this->hidden->buf_free -= this->hidden->mixlen; |
128 AuWriteElement(this->hidden->aud, this->hidden->flow, 0, this->hidden->mixlen, this->hidden->mixbuf, AuFalse, NULL); | 132 |
129 | 133 /* Write the audio data */ |
130 this->hidden->written += this->hidden->mixlen; | 134 AuWriteElement (this->hidden->aud, this->hidden->flow, 0, |
131 | 135 this->hidden->mixlen, this->hidden->mixbuf, AuFalse, |
136 NULL); | |
137 | |
138 this->hidden->written += this->hidden->mixlen; | |
139 | |
132 #ifdef DEBUG_AUDIO | 140 #ifdef DEBUG_AUDIO |
133 fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen); | 141 fprintf (stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen); |
134 #endif | 142 #endif |
135 } | 143 } |
136 | 144 |
137 static Uint8 *NAS_GetAudioBuf(_THIS) | 145 static Uint8 * |
138 { | 146 NAS_GetAudioBuf (_THIS) |
139 return(this->hidden->mixbuf); | 147 { |
140 } | 148 return (this->hidden->mixbuf); |
141 | 149 } |
142 static void NAS_CloseAudio(_THIS) | 150 |
143 { | 151 static void |
144 if ( this->hidden->mixbuf != NULL ) { | 152 NAS_CloseAudio (_THIS) |
145 SDL_FreeAudioMem(this->hidden->mixbuf); | 153 { |
146 this->hidden->mixbuf = NULL; | 154 if (this->hidden->mixbuf != NULL) { |
147 } | 155 SDL_FreeAudioMem (this->hidden->mixbuf); |
148 if ( this->hidden->aud ) { | 156 this->hidden->mixbuf = NULL; |
149 AuCloseServer(this->hidden->aud); | 157 } |
150 this->hidden->aud = 0; | 158 if (this->hidden->aud) { |
151 } | 159 AuCloseServer (this->hidden->aud); |
152 } | 160 this->hidden->aud = 0; |
153 | 161 } |
154 static unsigned char sdlformat_to_auformat(unsigned int fmt) | 162 } |
155 { | 163 |
156 switch (fmt) | 164 static unsigned char |
157 { | 165 sdlformat_to_auformat (unsigned int fmt) |
166 { | |
167 switch (fmt) { | |
158 case AUDIO_U8: | 168 case AUDIO_U8: |
159 return AuFormatLinearUnsigned8; | 169 return AuFormatLinearUnsigned8; |
160 case AUDIO_S8: | 170 case AUDIO_S8: |
161 return AuFormatLinearSigned8; | 171 return AuFormatLinearSigned8; |
162 case AUDIO_U16LSB: | 172 case AUDIO_U16LSB: |
163 return AuFormatLinearUnsigned16LSB; | 173 return AuFormatLinearUnsigned16LSB; |
164 case AUDIO_U16MSB: | 174 case AUDIO_U16MSB: |
165 return AuFormatLinearUnsigned16MSB; | 175 return AuFormatLinearUnsigned16MSB; |
166 case AUDIO_S16LSB: | 176 case AUDIO_S16LSB: |
167 return AuFormatLinearSigned16LSB; | 177 return AuFormatLinearSigned16LSB; |
168 case AUDIO_S16MSB: | 178 case AUDIO_S16MSB: |
169 return AuFormatLinearSigned16MSB; | 179 return AuFormatLinearSigned16MSB; |
170 } | 180 } |
171 return AuNone; | 181 return AuNone; |
172 } | 182 } |
173 | 183 |
174 static AuBool | 184 static AuBool |
175 event_handler(AuServer* aud, AuEvent* ev, AuEventHandlerRec* hnd) | 185 event_handler (AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd) |
176 { | 186 { |
177 switch (ev->type) { | 187 switch (ev->type) { |
178 case AuEventTypeElementNotify: { | 188 case AuEventTypeElementNotify: |
179 AuElementNotifyEvent* event = (AuElementNotifyEvent *)ev; | 189 { |
180 | 190 AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev; |
181 switch (event->kind) { | 191 |
182 case AuElementNotifyKindLowWater: | 192 switch (event->kind) { |
183 if (this2->buf_free >= 0) { | 193 case AuElementNotifyKindLowWater: |
184 this2->really += event->num_bytes; | 194 if (this2->buf_free >= 0) { |
185 gettimeofday(&this2->last_tv, 0); | 195 this2->really += event->num_bytes; |
186 this2->buf_free += event->num_bytes; | 196 gettimeofday (&this2->last_tv, 0); |
187 } else { | 197 this2->buf_free += event->num_bytes; |
188 this2->buf_free = event->num_bytes; | 198 } else { |
189 } | 199 this2->buf_free = event->num_bytes; |
190 break; | 200 } |
191 case AuElementNotifyKindState: | 201 break; |
192 switch (event->cur_state) { | 202 case AuElementNotifyKindState: |
193 case AuStatePause: | 203 switch (event->cur_state) { |
194 if (event->reason != AuReasonUser) { | 204 case AuStatePause: |
195 if (this2->buf_free >= 0) { | 205 if (event->reason != AuReasonUser) { |
196 this2->really += event->num_bytes; | 206 if (this2->buf_free >= 0) { |
197 gettimeofday(&this2->last_tv, 0); | 207 this2->really += event->num_bytes; |
198 this2->buf_free += event->num_bytes; | 208 gettimeofday (&this2->last_tv, 0); |
199 } else { | 209 this2->buf_free += event->num_bytes; |
200 this2->buf_free = event->num_bytes; | 210 } else { |
201 } | 211 this2->buf_free = event->num_bytes; |
202 } | 212 } |
203 break; | 213 } |
204 } | 214 break; |
205 } | 215 } |
206 } | 216 } |
207 } | 217 } |
208 return AuTrue; | 218 } |
219 return AuTrue; | |
209 } | 220 } |
210 | 221 |
211 static AuDeviceID | 222 static AuDeviceID |
212 find_device(_THIS, int nch) | 223 find_device (_THIS, int nch) |
213 { | 224 { |
214 int i; | 225 int i; |
215 for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) { | 226 for (i = 0; i < AuServerNumDevices (this->hidden->aud); i++) { |
216 if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) == | 227 if ((AuDeviceKind (AuServerDevice (this->hidden->aud, i)) == |
217 AuComponentKindPhysicalOutput) && | 228 AuComponentKindPhysicalOutput) && |
218 AuDeviceNumTracks(AuServerDevice(this->hidden->aud, i)) == nch) { | 229 AuDeviceNumTracks (AuServerDevice (this->hidden->aud, i)) == |
219 return AuDeviceIdentifier(AuServerDevice(this->hidden->aud, i)); | 230 nch) { |
220 } | 231 return AuDeviceIdentifier (AuServerDevice (this->hidden->aud, i)); |
221 } | 232 } |
222 return AuNone; | 233 } |
223 } | 234 return AuNone; |
224 | 235 } |
225 static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec) | 236 |
226 { | 237 static int |
227 AuElement elms[3]; | 238 NAS_OpenAudio (_THIS, SDL_AudioSpec * spec) |
228 int buffer_size; | 239 { |
229 Uint16 test_format, format; | 240 AuElement elms[3]; |
230 | 241 int buffer_size; |
231 this->hidden->mixbuf = NULL; | 242 Uint16 test_format, format; |
232 | 243 |
233 /* Try for a closest match on audio format */ | 244 this->hidden->mixbuf = NULL; |
234 format = 0; | 245 |
235 for ( test_format = SDL_FirstAudioFormat(spec->format); | 246 /* Try for a closest match on audio format */ |
236 ! format && test_format; ) { | 247 format = 0; |
237 format = sdlformat_to_auformat(test_format); | 248 for (test_format = SDL_FirstAudioFormat (spec->format); |
238 | 249 !format && test_format;) { |
239 if (format == AuNone) { | 250 format = sdlformat_to_auformat (test_format); |
240 test_format = SDL_NextAudioFormat(); | 251 |
241 } | 252 if (format == AuNone) { |
242 } | 253 test_format = SDL_NextAudioFormat (); |
243 if ( format == 0 ) { | 254 } |
244 SDL_SetError("Couldn't find any hardware audio formats"); | 255 } |
245 return(-1); | 256 if (format == 0) { |
246 } | 257 SDL_SetError ("Couldn't find any hardware audio formats"); |
247 spec->format = test_format; | 258 return (-1); |
248 | 259 } |
249 this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL); | 260 spec->format = test_format; |
250 if (this->hidden->aud == 0) | 261 |
251 { | 262 this->hidden->aud = AuOpenServer ("", 0, NULL, 0, NULL, NULL); |
252 SDL_SetError("Couldn't open connection to NAS server"); | 263 if (this->hidden->aud == 0) { |
253 return (-1); | 264 SDL_SetError ("Couldn't open connection to NAS server"); |
254 } | 265 return (-1); |
255 | 266 } |
256 this->hidden->dev = find_device(this, spec->channels); | 267 |
257 if ((this->hidden->dev == AuNone) || (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) { | 268 this->hidden->dev = find_device (this, spec->channels); |
258 AuCloseServer(this->hidden->aud); | 269 if ((this->hidden->dev == AuNone) |
259 this->hidden->aud = 0; | 270 || (!(this->hidden->flow = AuCreateFlow (this->hidden->aud, NULL)))) { |
260 SDL_SetError("Couldn't find a fitting playback device on NAS server"); | 271 AuCloseServer (this->hidden->aud); |
261 return (-1); | 272 this->hidden->aud = 0; |
262 } | 273 SDL_SetError |
263 | 274 ("Couldn't find a fitting playback device on NAS server"); |
264 buffer_size = spec->freq; | 275 return (-1); |
265 if (buffer_size < 4096) | 276 } |
266 buffer_size = 4096; | 277 |
267 | 278 buffer_size = spec->freq; |
268 if (buffer_size > 32768) | 279 if (buffer_size < 4096) |
269 buffer_size = 32768; /* So that the buffer won't get unmanageably big. */ | 280 buffer_size = 4096; |
270 | 281 |
271 /* Calculate the final parameters for this audio specification */ | 282 if (buffer_size > 32768) |
272 SDL_CalculateAudioSpec(spec); | 283 buffer_size = 32768; /* So that the buffer won't get unmanageably big. */ |
273 | 284 |
274 this2 = this->hidden; | 285 /* Calculate the final parameters for this audio specification */ |
275 | 286 SDL_CalculateAudioSpec (spec); |
276 AuMakeElementImportClient(elms, spec->freq, format, spec->channels, AuTrue, | 287 |
277 buffer_size, buffer_size / 4, 0, NULL); | 288 this2 = this->hidden; |
278 AuMakeElementExportDevice(elms+1, 0, this->hidden->dev, spec->freq, | 289 |
279 AuUnlimitedSamples, 0, NULL); | 290 AuMakeElementImportClient (elms, spec->freq, format, spec->channels, |
280 AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, NULL); | 291 AuTrue, buffer_size, buffer_size / 4, 0, NULL); |
281 AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0, this->hidden->flow, | 292 AuMakeElementExportDevice (elms + 1, 0, this->hidden->dev, spec->freq, |
282 event_handler, (AuPointer) NULL); | 293 AuUnlimitedSamples, 0, NULL); |
283 | 294 AuSetElements (this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, |
284 AuStartFlow(this->hidden->aud, this->hidden->flow, NULL); | 295 NULL); |
285 | 296 AuRegisterEventHandler (this->hidden->aud, AuEventHandlerIDMask, 0, |
286 /* Allocate mixing buffer */ | 297 this->hidden->flow, event_handler, |
287 this->hidden->mixlen = spec->size; | 298 (AuPointer) NULL); |
288 this->hidden->mixbuf = (Uint8 *)SDL_AllocAudioMem(this->hidden->mixlen); | 299 |
289 if ( this->hidden->mixbuf == NULL ) { | 300 AuStartFlow (this->hidden->aud, this->hidden->flow, NULL); |
290 return(-1); | 301 |
291 } | 302 /* Allocate mixing buffer */ |
292 SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); | 303 this->hidden->mixlen = spec->size; |
293 | 304 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem (this->hidden->mixlen); |
294 /* Get the parent process id (we're the parent of the audio thread) */ | 305 if (this->hidden->mixbuf == NULL) { |
295 this->hidden->parent = getpid(); | 306 return (-1); |
296 | 307 } |
297 /* We're ready to rock and roll. :-) */ | 308 SDL_memset (this->hidden->mixbuf, spec->silence, spec->size); |
298 return(0); | 309 |
299 } | 310 /* Get the parent process id (we're the parent of the audio thread) */ |
311 this->hidden->parent = getpid (); | |
312 | |
313 /* We're ready to rock and roll. :-) */ | |
314 return (0); | |
315 } | |
316 | |
317 /* vi: set ts=4 sw=4 expandtab: */ |