Mercurial > sdl-ios-xcode
comparison src/audio/bsd/SDL_bsdaudio.c @ 2049:5f6550e5184f
Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Tue, 17 Oct 2006 09:15:21 +0000 |
parents | 3b4ce57c6215 |
children | 866052b01ee5 |
comparison
equal
deleted
inserted
replaced
2048:6067c7f9a672 | 2049:5f6550e5184f |
---|---|
59 | 59 |
60 /* #define DEBUG_AUDIO */ | 60 /* #define DEBUG_AUDIO */ |
61 /* #define DEBUG_AUDIO_STREAM */ | 61 /* #define DEBUG_AUDIO_STREAM */ |
62 | 62 |
63 #ifdef USE_BLOCKING_WRITES | 63 #ifdef USE_BLOCKING_WRITES |
64 #define OPEN_FLAGS O_WRONLY | 64 #define OPEN_FLAGS_OUTPUT O_WRONLY |
65 #define OPEN_FLAGS_INPUT O_RDONLY | |
65 #else | 66 #else |
66 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) | 67 #define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK) |
67 #endif | 68 #define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) |
68 | 69 #endif |
69 /* Audio driver functions */ | 70 |
70 static void OBSD_WaitAudio(_THIS); | 71 /* !!! FIXME: so much cut and paste with dsp/dma drivers... */ |
71 static int OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec); | 72 static char **outputDevices = NULL; |
72 static void OBSD_PlayAudio(_THIS); | 73 static int outputDeviceCount = 0; |
73 static Uint8 *OBSD_GetAudioBuf(_THIS); | 74 static char **inputDevices = NULL; |
74 static void OBSD_CloseAudio(_THIS); | 75 static int inputDeviceCount = 0; |
75 | 76 |
77 static inline void | |
78 free_device_list(char ***devs, int *count) | |
79 { | |
80 SDL_FreeUnixAudioDevices(devs, count); | |
81 } | |
82 | |
83 static inline void | |
84 build_device_list(int iscapture, char ***devs, int *count) | |
85 { | |
86 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); | |
87 free_device_list(devs, count); | |
88 SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count); | |
89 } | |
90 | |
91 static inline void | |
92 build_device_lists(void) | |
93 { | |
94 build_device_list(0, &outputDevices, &outputDeviceCount); | |
95 build_device_list(1, &inputDevices, &inputDeviceCount); | |
96 } | |
97 | |
98 | |
99 static inline void | |
100 free_device_lists(void) | |
101 { | |
102 free_device_list(&outputDevices, &outputDeviceCount); | |
103 free_device_list(&inputDevices, &inputDeviceCount); | |
104 } | |
105 | |
106 | |
107 static void | |
108 BSDAUDIO_Deinitialize(void) | |
109 { | |
110 free_device_lists(); | |
111 } | |
112 | |
113 | |
114 static int | |
115 BSDAUDIO_DetectDevices(int iscapture) | |
116 { | |
117 if (iscapture) { | |
118 build_device_list(1, &inputDevices, &inputDeviceCount); | |
119 return inputDeviceCount; | |
120 } else { | |
121 build_device_list(0, &outputDevices, &outputDeviceCount); | |
122 return outputDeviceCount; | |
123 } | |
124 | |
125 return 0; /* shouldn't ever hit this. */ | |
126 } | |
127 | |
128 static const char * | |
129 BSDAUDIO_GetDeviceName(int index, int iscapture) | |
130 { | |
131 if ((iscapture) && (index < inputDeviceCount)) { | |
132 return inputDevices[index]; | |
133 } else if ((!iscapture) && (index < outputDeviceCount)) { | |
134 return outputDevices[index]; | |
135 } | |
136 | |
137 SDL_SetError("No such device"); | |
138 return NULL; | |
139 } | |
140 | |
141 | |
142 static void | |
143 BSDAUDIO_Status(_THIS) | |
144 { | |
76 #ifdef DEBUG_AUDIO | 145 #ifdef DEBUG_AUDIO |
77 static void OBSD_Status(_THIS); | |
78 #endif | |
79 | |
80 /* Audio driver bootstrap functions */ | |
81 | |
82 static int | |
83 Audio_Available(void) | |
84 { | |
85 int fd; | |
86 int available; | |
87 | |
88 available = 0; | |
89 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); | |
90 if (fd >= 0) { | |
91 available = 1; | |
92 close(fd); | |
93 } | |
94 return (available); | |
95 } | |
96 | |
97 static void | |
98 Audio_DeleteDevice(SDL_AudioDevice * device) | |
99 { | |
100 SDL_free(device->hidden); | |
101 SDL_free(device); | |
102 } | |
103 | |
104 static SDL_AudioDevice * | |
105 Audio_CreateDevice(int devindex) | |
106 { | |
107 SDL_AudioDevice *this; | |
108 | |
109 /* Initialize all variables that we clean on shutdown */ | |
110 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); | |
111 if (this) { | |
112 SDL_memset(this, 0, (sizeof *this)); | |
113 this->hidden = (struct SDL_PrivateAudioData *) | |
114 SDL_malloc((sizeof *this->hidden)); | |
115 } | |
116 if ((this == NULL) || (this->hidden == NULL)) { | |
117 SDL_OutOfMemory(); | |
118 if (this) | |
119 SDL_free(this); | |
120 return (0); | |
121 } | |
122 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
123 audio_fd = -1; | |
124 | |
125 /* Set the function pointers */ | |
126 this->OpenAudio = OBSD_OpenAudio; | |
127 this->WaitAudio = OBSD_WaitAudio; | |
128 this->PlayAudio = OBSD_PlayAudio; | |
129 this->GetAudioBuf = OBSD_GetAudioBuf; | |
130 this->CloseAudio = OBSD_CloseAudio; | |
131 | |
132 this->free = Audio_DeleteDevice; | |
133 | |
134 return this; | |
135 } | |
136 | |
137 AudioBootStrap BSD_AUDIO_bootstrap = { | |
138 BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, | |
139 Audio_Available, Audio_CreateDevice | |
140 }; | |
141 | |
142 /* This function waits until it is possible to write a full sound buffer */ | |
143 static void | |
144 OBSD_WaitAudio(_THIS) | |
145 { | |
146 #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ | |
147 /* See if we need to use timed audio synchronization */ | |
148 if (frame_ticks) { | |
149 /* Use timer for general audio synchronization */ | |
150 Sint32 ticks; | |
151 | |
152 ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; | |
153 if (ticks > 0) { | |
154 SDL_Delay(ticks); | |
155 } | |
156 } else { | |
157 /* Use select() for audio synchronization */ | |
158 fd_set fdset; | |
159 struct timeval timeout; | |
160 | |
161 FD_ZERO(&fdset); | |
162 FD_SET(audio_fd, &fdset); | |
163 timeout.tv_sec = 10; | |
164 timeout.tv_usec = 0; | |
165 #ifdef DEBUG_AUDIO | |
166 fprintf(stderr, "Waiting for audio to get ready\n"); | |
167 #endif | |
168 if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) { | |
169 const char *message = | |
170 "Audio timeout - buggy audio driver? (disabled)"; | |
171 /* In general we should never print to the screen, | |
172 but in this case we have no other way of letting | |
173 the user know what happened. | |
174 */ | |
175 fprintf(stderr, "SDL: %s\n", message); | |
176 this->enabled = 0; | |
177 /* Don't try to close - may hang */ | |
178 audio_fd = -1; | |
179 #ifdef DEBUG_AUDIO | |
180 fprintf(stderr, "Done disabling audio\n"); | |
181 #endif | |
182 } | |
183 #ifdef DEBUG_AUDIO | |
184 fprintf(stderr, "Ready!\n"); | |
185 #endif | |
186 } | |
187 #endif /* !USE_BLOCKING_WRITES */ | |
188 } | |
189 | |
190 static void | |
191 OBSD_PlayAudio(_THIS) | |
192 { | |
193 int written, p = 0; | |
194 | |
195 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | |
196 do { | |
197 written = write(audio_fd, &mixbuf[p], mixlen - p); | |
198 if (written > 0) | |
199 p += written; | |
200 if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) { | |
201 /* Non recoverable error has occurred. It should be reported!!! */ | |
202 perror("audio"); | |
203 break; | |
204 } | |
205 | |
206 if (p < written | |
207 || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) { | |
208 SDL_Delay(1); /* Let a little CPU time go by */ | |
209 } | |
210 } | |
211 while (p < written); | |
212 | |
213 /* If timer synchronization is enabled, set the next write frame */ | |
214 if (frame_ticks) { | |
215 next_frame += frame_ticks; | |
216 } | |
217 | |
218 /* If we couldn't write, assume fatal error for now */ | |
219 if (written < 0) { | |
220 this->enabled = 0; | |
221 } | |
222 #ifdef DEBUG_AUDIO | |
223 fprintf(stderr, "Wrote %d bytes of audio data\n", written); | |
224 #endif | |
225 } | |
226 | |
227 static Uint8 * | |
228 OBSD_GetAudioBuf(_THIS) | |
229 { | |
230 return (mixbuf); | |
231 } | |
232 | |
233 static void | |
234 OBSD_CloseAudio(_THIS) | |
235 { | |
236 if (mixbuf != NULL) { | |
237 SDL_FreeAudioMem(mixbuf); | |
238 mixbuf = NULL; | |
239 } | |
240 if (audio_fd >= 0) { | |
241 close(audio_fd); | |
242 audio_fd = -1; | |
243 } | |
244 } | |
245 | |
246 #ifdef DEBUG_AUDIO | |
247 void | |
248 OBSD_Status(_THIS) | |
249 { | |
250 audio_info_t info; | 146 audio_info_t info; |
251 | 147 |
252 if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) { | 148 if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) { |
253 fprintf(stderr, "AUDIO_GETINFO failed.\n"); | 149 fprintf(stderr, "AUDIO_GETINFO failed.\n"); |
254 return; | 150 return; |
255 } | 151 } |
256 | 152 |
257 fprintf(stderr, "\n" | 153 fprintf(stderr, "\n" |
267 "paused : %s\n" | 163 "paused : %s\n" |
268 "error occured : %s\n" | 164 "error occured : %s\n" |
269 "waiting : %s\n" | 165 "waiting : %s\n" |
270 "active : %s\n" | 166 "active : %s\n" |
271 "", | 167 "", |
272 info. | 168 info.play.buffer_size, |
273 play. | 169 info.play.sample_rate, |
274 buffer_size, | 170 info.play.channels, |
275 info. | 171 info.play.precision, |
276 play. | 172 info.play.encoding, |
277 sample_rate, | 173 info.play.seek, |
278 info. | 174 info.play.samples, |
279 play. | 175 info.play.eof, |
280 channels, | 176 info.play.pause ? "yes" : "no", |
281 info. | 177 info.play.error ? "yes" : "no", |
282 play. | 178 info.play.waiting ? "yes" : "no", |
283 precision, | 179 info.play.active ? "yes" : "no"); |
284 info. | |
285 play. | |
286 encoding, | |
287 info. | |
288 play. | |
289 seek, | |
290 info. | |
291 play. | |
292 samples, | |
293 info. | |
294 play. | |
295 eof, | |
296 info. | |
297 play. | |
298 pause | |
299 ? | |
300 "yes" | |
301 : | |
302 "no", | |
303 info. | |
304 play. | |
305 error | |
306 ? | |
307 "yes" | |
308 : | |
309 "no", | |
310 info. | |
311 play.waiting ? "yes" : "no", info.play.active ? "yes" : "no"); | |
312 | 180 |
313 fprintf(stderr, "\n" | 181 fprintf(stderr, "\n" |
314 "[audio info]\n" | 182 "[audio info]\n" |
315 "monitor_gain : %i\n" | 183 "monitor_gain : %i\n" |
316 "hw block size : %d bytes\n" | 184 "hw block size : %d bytes\n" |
322 info.blocksize, | 190 info.blocksize, |
323 info.hiwat, info.lowat, | 191 info.hiwat, info.lowat, |
324 (info.mode == AUMODE_PLAY) ? "PLAY" | 192 (info.mode == AUMODE_PLAY) ? "PLAY" |
325 : (info.mode = AUMODE_RECORD) ? "RECORD" | 193 : (info.mode = AUMODE_RECORD) ? "RECORD" |
326 : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?")); | 194 : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?")); |
327 } | |
328 #endif /* DEBUG_AUDIO */ | 195 #endif /* DEBUG_AUDIO */ |
196 } | |
197 | |
198 | |
199 /* This function waits until it is possible to write a full sound buffer */ | |
200 static void | |
201 BSDAUDIO_WaitDevice(_THIS) | |
202 { | |
203 #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ | |
204 /* See if we need to use timed audio synchronization */ | |
205 if (this->hidden->frame_ticks) { | |
206 /* Use timer for general audio synchronization */ | |
207 Sint32 ticks; | |
208 | |
209 ticks = ((Sint32)(this->hidden->next_frame-SDL_GetTicks()))-FUDGE_TICKS; | |
210 if (ticks > 0) { | |
211 SDL_Delay(ticks); | |
212 } | |
213 } else { | |
214 /* Use select() for audio synchronization */ | |
215 fd_set fdset; | |
216 struct timeval timeout; | |
217 | |
218 FD_ZERO(&fdset); | |
219 FD_SET(this->hidden->audio_fd, &fdset); | |
220 timeout.tv_sec = 10; | |
221 timeout.tv_usec = 0; | |
222 #ifdef DEBUG_AUDIO | |
223 fprintf(stderr, "Waiting for audio to get ready\n"); | |
224 #endif | |
225 if (select(this->hidden->audio_fd+1,NULL,&fdset,NULL,&timeout) <= 0) { | |
226 const char *message = | |
227 "Audio timeout - buggy audio driver? (disabled)"; | |
228 /* In general we should never print to the screen, | |
229 but in this case we have no other way of letting | |
230 the user know what happened. | |
231 */ | |
232 fprintf(stderr, "SDL: %s\n", message); | |
233 this->enabled = 0; | |
234 /* Don't try to close - may hang */ | |
235 this->hidden->audio_fd = -1; | |
236 #ifdef DEBUG_AUDIO | |
237 fprintf(stderr, "Done disabling audio\n"); | |
238 #endif | |
239 } | |
240 #ifdef DEBUG_AUDIO | |
241 fprintf(stderr, "Ready!\n"); | |
242 #endif | |
243 } | |
244 #endif /* !USE_BLOCKING_WRITES */ | |
245 } | |
246 | |
247 static void | |
248 BSDAUDIO_PlayDevice(_THIS) | |
249 { | |
250 int written, p = 0; | |
251 | |
252 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | |
253 do { | |
254 written = write(this->hidden->audio_fd, | |
255 &this->hidden->mixbuf[p], | |
256 this->hidden->mixlen - p); | |
257 | |
258 if (written > 0) | |
259 p += written; | |
260 if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) { | |
261 /* Non recoverable error has occurred. It should be reported!!! */ | |
262 perror("audio"); | |
263 break; | |
264 } | |
265 | |
266 if (p < written | |
267 || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) { | |
268 SDL_Delay(1); /* Let a little CPU time go by */ | |
269 } | |
270 } | |
271 while (p < written); | |
272 | |
273 /* If timer synchronization is enabled, set the next write frame */ | |
274 if (this->hidden->frame_ticks) { | |
275 this->hidden->next_frame += this->hidden->frame_ticks; | |
276 } | |
277 | |
278 /* If we couldn't write, assume fatal error for now */ | |
279 if (written < 0) { | |
280 this->enabled = 0; | |
281 } | |
282 #ifdef DEBUG_AUDIO | |
283 fprintf(stderr, "Wrote %d bytes of audio data\n", written); | |
284 #endif | |
285 } | |
286 | |
287 static Uint8 * | |
288 BSDAUDIO_GetDeviceBuf(_THIS) | |
289 { | |
290 return (this->hidden->mixbuf); | |
291 } | |
292 | |
293 static void | |
294 BSDAUDIO_CloseDevice(_THIS) | |
295 { | |
296 if (this->hidden != NULL) { | |
297 if (this->hidden->mixbuf != NULL) { | |
298 SDL_FreeAudioMem(this->hidden->mixbuf); | |
299 this->hidden->mixbuf = NULL; | |
300 } | |
301 if (this->hidden->audio_fd >= 0) { | |
302 close(this->hidden->audio_fd); | |
303 this->hidden->audio_fd = -1; | |
304 } | |
305 SDL_free(this->hidden); | |
306 this->hidden = NULL; | |
307 } | |
308 } | |
329 | 309 |
330 static int | 310 static int |
331 OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec) | 311 BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) |
332 { | 312 { |
333 char audiodev[64]; | 313 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); |
334 SDL_AudioFormat format; | 314 SDL_AudioFormat format = 0; |
335 audio_info_t info; | 315 audio_info_t info; |
336 | 316 |
317 /* We don't care what the devname is...we'll try to open anything. */ | |
318 /* ...but default to first name in the list... */ | |
319 if (devname == NULL) { | |
320 if ( ((iscapture) && (inputDeviceCount == 0)) || | |
321 ((!iscapture) && (outputDeviceCount == 0)) ) { | |
322 SDL_SetError("No such audio device"); | |
323 return 0; | |
324 } | |
325 devname = ((iscapture) ? inputDevices[0] : outputDevices[0]); | |
326 } | |
327 | |
328 /* Initialize all variables that we clean on shutdown */ | |
329 this->hidden = (struct SDL_PrivateAudioData *) | |
330 SDL_malloc((sizeof *this->hidden)); | |
331 if (this->hidden == NULL) { | |
332 SDL_OutOfMemory(); | |
333 return 0; | |
334 } | |
335 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
336 | |
337 /* Open the audio device */ | |
338 this->hidden->audio_fd = open(devname, flags, 0); | |
339 if (this->hidden->audio_fd < 0) { | |
340 SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); | |
341 return 0; | |
342 } | |
343 | |
337 AUDIO_INITINFO(&info); | 344 AUDIO_INITINFO(&info); |
338 | 345 |
339 /* Calculate the final parameters for this audio specification */ | 346 /* Calculate the final parameters for this audio specification */ |
340 SDL_CalculateAudioSpec(spec); | 347 SDL_CalculateAudioSpec(&this->spec); |
341 | |
342 #ifdef USE_TIMER_SYNC | |
343 frame_ticks = 0.0; | |
344 #endif | |
345 | |
346 /* Open the audio device */ | |
347 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); | |
348 if (audio_fd < 0) { | |
349 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | |
350 return (-1); | |
351 } | |
352 | 348 |
353 /* Set to play mode */ | 349 /* Set to play mode */ |
354 info.mode = AUMODE_PLAY; | 350 info.mode = AUMODE_PLAY; |
355 if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { | 351 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) { |
352 BSDAUDIO_CloseDevice(this); | |
356 SDL_SetError("Couldn't put device into play mode"); | 353 SDL_SetError("Couldn't put device into play mode"); |
357 return (-1); | 354 return 0; |
358 } | 355 } |
359 | 356 |
360 mixbuf = NULL; | |
361 AUDIO_INITINFO(&info); | 357 AUDIO_INITINFO(&info); |
362 for (format = SDL_FirstAudioFormat(spec->format); | 358 for (format = SDL_FirstAudioFormat(this->spec.format); |
363 format; format = SDL_NextAudioFormat()) { | 359 format; format = SDL_NextAudioFormat()) { |
364 switch (format) { | 360 switch (format) { |
365 case AUDIO_U8: | 361 case AUDIO_U8: |
366 info.play.encoding = AUDIO_ENCODING_ULINEAR; | 362 info.play.encoding = AUDIO_ENCODING_ULINEAR; |
367 info.play.precision = 8; | 363 info.play.precision = 8; |
387 info.play.precision = 16; | 383 info.play.precision = 16; |
388 break; | 384 break; |
389 default: | 385 default: |
390 continue; | 386 continue; |
391 } | 387 } |
392 if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0) | 388 |
393 break; | 389 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) { |
390 break; | |
391 } | |
394 } | 392 } |
395 | 393 |
396 if (!format) { | 394 if (!format) { |
397 SDL_SetError("No supported encoding for 0x%x", spec->format); | 395 BSDAUDIO_CloseDevice(this); |
398 return (-1); | 396 SDL_SetError("No supported encoding for 0x%x", this->spec.format); |
399 } | 397 return 0; |
400 | 398 } |
401 spec->format = format; | 399 |
400 this->spec.format = format; | |
402 | 401 |
403 AUDIO_INITINFO(&info); | 402 AUDIO_INITINFO(&info); |
404 info.play.channels = spec->channels; | 403 info.play.channels = this->spec.channels; |
405 if (ioctl(audio_fd, AUDIO_SETINFO, &info) == -1) | 404 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) { |
406 spec->channels = 1; | 405 this->spec.channels = 1; |
406 } | |
407 AUDIO_INITINFO(&info); | 407 AUDIO_INITINFO(&info); |
408 info.play.sample_rate = spec->freq; | 408 info.play.sample_rate = this->spec.freq; |
409 info.blocksize = spec->size; | 409 info.blocksize = this->spec.size; |
410 info.hiwat = 5; | 410 info.hiwat = 5; |
411 info.lowat = 3; | 411 info.lowat = 3; |
412 (void) ioctl(audio_fd, AUDIO_SETINFO, &info); | 412 (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info); |
413 (void) ioctl(audio_fd, AUDIO_GETINFO, &info); | 413 (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info); |
414 spec->freq = info.play.sample_rate; | 414 this->spec.freq = info.play.sample_rate; |
415 /* Allocate mixing buffer */ | 415 /* Allocate mixing buffer */ |
416 mixlen = spec->size; | 416 this->hidden->mixlen = this->spec.size; |
417 mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); | 417 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); |
418 if (mixbuf == NULL) { | 418 if (this->hidden->mixbuf == NULL) { |
419 return (-1); | 419 BSDAUDIO_CloseDevice(this); |
420 } | 420 SDL_OutOfMemory(); |
421 SDL_memset(mixbuf, spec->silence, spec->size); | 421 return 0; |
422 | 422 } |
423 /* Get the parent process id (we're the parent of the audio thread) */ | 423 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); |
424 parent = getpid(); | 424 |
425 | 425 BSDAUDIO_Status(this); |
426 #ifdef DEBUG_AUDIO | |
427 OBSD_Status(this); | |
428 #endif | |
429 | 426 |
430 /* We're ready to rock and roll. :-) */ | 427 /* We're ready to rock and roll. :-) */ |
431 return (0); | 428 return (0); |
432 } | 429 } |
433 | 430 |
431 static int | |
432 BSDAUDIO_Init(SDL_AudioDriverImpl *impl) | |
433 { | |
434 /* Set the function pointers */ | |
435 impl->DetectDevices = BSDAUDIO_DetectDevices; | |
436 impl->GetDeviceName = BSDAUDIO_GetDeviceName; | |
437 impl->OpenDevice = BSDAUDIO_OpenDevice; | |
438 impl->PlayDevice = BSDAUDIO_PlayDevice; | |
439 impl->WaitDevice = BSDAUDIO_WaitDevice; | |
440 impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf; | |
441 impl->CloseDevice = BSDAUDIO_CloseDevice; | |
442 impl->Deinitialize = BSDAUDIO_Deinitialize; | |
443 | |
444 build_device_lists(); | |
445 return 1; | |
446 } | |
447 | |
448 | |
449 AudioBootStrap BSD_AUDIO_bootstrap = { | |
450 BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, BSDAUDIO_Init, 0 | |
451 }; | |
452 | |
434 /* vi: set ts=4 sw=4 expandtab: */ | 453 /* vi: set ts=4 sw=4 expandtab: */ |