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: */