Mercurial > sdl-ios-xcode
comparison src/audio/SDL_audio.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 | 510892a215a2 |
children | 716cf90f24a0 |
comparison
equal
deleted
inserted
replaced
2048:6067c7f9a672 | 2049:5f6550e5184f |
---|---|
26 #include "SDL.h" | 26 #include "SDL.h" |
27 #include "SDL_audio_c.h" | 27 #include "SDL_audio_c.h" |
28 #include "SDL_audiomem.h" | 28 #include "SDL_audiomem.h" |
29 #include "SDL_sysaudio.h" | 29 #include "SDL_sysaudio.h" |
30 | 30 |
31 #ifdef __OS2__ | 31 #define _THIS SDL_AudioDevice *this |
32 /* We'll need the DosSetPriority() API! */ | 32 |
33 #define INCL_DOSPROCESS | 33 static SDL_AudioDriver current_audio; |
34 #include <os2.h> | 34 static SDL_AudioDevice *open_devices[16]; |
35 #endif | 35 |
36 /* !!! FIXME: These are wordy and unlocalized... */ | |
37 #define DEFAULT_OUTPUT_DEVNAME "System audio output device" | |
38 #define DEFAULT_INPUT_DEVNAME "System audio capture device" | |
39 | |
40 | |
41 /* | |
42 * Not all of these will be compiled and linked in, but it's convenient | |
43 * to have a complete list here and saves yet-another block of #ifdefs... | |
44 * Please see bootstrap[], below, for the actual #ifdef mess. | |
45 */ | |
46 extern AudioBootStrap BSD_AUDIO_bootstrap; | |
47 extern AudioBootStrap DSP_bootstrap; | |
48 extern AudioBootStrap DMA_bootstrap; | |
49 extern AudioBootStrap ALSA_bootstrap; | |
50 extern AudioBootStrap QNXNTOAUDIO_bootstrap; | |
51 extern AudioBootStrap SUNAUDIO_bootstrap; | |
52 extern AudioBootStrap DMEDIA_bootstrap; | |
53 extern AudioBootStrap ARTS_bootstrap; | |
54 extern AudioBootStrap ESD_bootstrap; | |
55 extern AudioBootStrap NAS_bootstrap; | |
56 extern AudioBootStrap DSOUND_bootstrap; | |
57 extern AudioBootStrap WAVEOUT_bootstrap; | |
58 extern AudioBootStrap PAUDIO_bootstrap; | |
59 extern AudioBootStrap BEOSAUDIO_bootstrap; | |
60 extern AudioBootStrap COREAUDIO_bootstrap; | |
61 extern AudioBootStrap SNDMGR_bootstrap; | |
62 extern AudioBootStrap MINTAUDIO_GSXB_bootstrap; | |
63 extern AudioBootStrap MINTAUDIO_MCSN_bootstrap; | |
64 extern AudioBootStrap MINTAUDIO_STFA_bootstrap; | |
65 extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap; | |
66 extern AudioBootStrap MINTAUDIO_DMA8_bootstrap; | |
67 extern AudioBootStrap DISKAUD_bootstrap; | |
68 extern AudioBootStrap DUMMYAUD_bootstrap; | |
69 extern AudioBootStrap DCAUD_bootstrap; | |
70 extern AudioBootStrap MMEAUDIO_bootstrap; | |
71 extern AudioBootStrap DART_bootstrap; | |
72 | |
36 | 73 |
37 /* Available audio drivers */ | 74 /* Available audio drivers */ |
38 static AudioBootStrap *bootstrap[] = { | 75 static AudioBootStrap *bootstrap[] = { |
39 #if SDL_AUDIO_DRIVER_BSD | 76 #if SDL_AUDIO_DRIVER_BSD |
40 &BSD_AUDIO_bootstrap, | 77 &BSD_AUDIO_bootstrap, |
68 &DSOUND_bootstrap, | 105 &DSOUND_bootstrap, |
69 #endif | 106 #endif |
70 #if SDL_AUDIO_DRIVER_WAVEOUT | 107 #if SDL_AUDIO_DRIVER_WAVEOUT |
71 &WAVEOUT_bootstrap, | 108 &WAVEOUT_bootstrap, |
72 #endif | 109 #endif |
73 #if SDL_AUDIO_DRIVER_PAUD | 110 #if SDL_AUDIO_DRIVER_PAUDIO |
74 &Paud_bootstrap, | 111 &PAUDIO_bootstrap, |
75 #endif | 112 #endif |
76 #if SDL_AUDIO_DRIVER_BAUDIO | 113 #if SDL_AUDIO_DRIVER_BEOSAUDIO |
77 &BAUDIO_bootstrap, | 114 &BEOSAUDIO_bootstrap, |
78 #endif | 115 #endif |
79 #if SDL_AUDIO_DRIVER_COREAUDIO | 116 #if SDL_AUDIO_DRIVER_COREAUDIO |
80 &COREAUDIO_bootstrap, | 117 &COREAUDIO_bootstrap, |
81 #endif | 118 #endif |
82 #if SDL_AUDIO_DRIVER_SNDMGR | 119 #if SDL_AUDIO_DRIVER_SNDMGR |
83 &SNDMGR_bootstrap, | 120 &SNDMGR_bootstrap, |
84 #endif | |
85 #if SDL_AUDIO_DRIVER_AHI | |
86 &AHI_bootstrap, | |
87 #endif | 121 #endif |
88 #if SDL_AUDIO_DRIVER_MINT | 122 #if SDL_AUDIO_DRIVER_MINT |
89 &MINTAUDIO_GSXB_bootstrap, | 123 &MINTAUDIO_GSXB_bootstrap, |
90 &MINTAUDIO_MCSN_bootstrap, | 124 &MINTAUDIO_MCSN_bootstrap, |
91 &MINTAUDIO_STFA_bootstrap, | 125 &MINTAUDIO_STFA_bootstrap, |
107 #if SDL_AUDIO_DRIVER_DART | 141 #if SDL_AUDIO_DRIVER_DART |
108 &DART_bootstrap, | 142 &DART_bootstrap, |
109 #endif | 143 #endif |
110 NULL | 144 NULL |
111 }; | 145 }; |
112 SDL_AudioDevice *current_audio = NULL; | 146 |
113 | 147 static SDL_AudioDevice *get_audio_device(SDL_AudioDeviceID id) |
114 /* Various local functions */ | 148 { |
115 int SDL_AudioInit(const char *driver_name); | 149 id--; |
116 void SDL_AudioQuit(void); | 150 if ( (id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL) ) { |
117 | 151 SDL_SetError("Invalid audio device ID"); |
118 #if SDL_AUDIO_DRIVER_AHI | 152 return NULL; |
119 static int audio_configured = 0; | 153 } |
120 #endif | 154 |
155 return open_devices[id]; | |
156 } | |
157 | |
158 | |
159 /* stubs for audio drivers that don't need a specific entry point... */ | |
160 static int SDL_AudioDetectDevices_Default(int iscapture) { return -1; } | |
161 static void SDL_AudioThreadInit_Default(_THIS) { /* no-op. */ } | |
162 static void SDL_AudioWaitDevice_Default(_THIS) { /* no-op. */ } | |
163 static void SDL_AudioPlayDevice_Default(_THIS) { /* no-op. */ } | |
164 static Uint8 *SDL_AudioGetDeviceBuf_Default(_THIS) { return NULL; } | |
165 static void SDL_AudioWaitDone_Default(_THIS) { /* no-op. */ } | |
166 static void SDL_AudioCloseDevice_Default(_THIS) { /* no-op. */ } | |
167 static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ } | |
168 | |
169 static int | |
170 SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture) | |
171 { | |
172 return 0; | |
173 } | |
174 | |
175 static const char *SDL_AudioGetDeviceName_Default(int index, int iscapture) | |
176 { | |
177 SDL_SetError("No such device"); | |
178 return NULL; | |
179 } | |
180 | |
181 static void | |
182 SDL_AudioLockDevice_Default(SDL_AudioDevice * device) | |
183 { | |
184 if (device->thread && (SDL_ThreadID() == device->threadid)) { | |
185 return; | |
186 } | |
187 SDL_mutexP(device->mixer_lock); | |
188 } | |
189 | |
190 static void | |
191 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device) | |
192 { | |
193 if (device->thread && (SDL_ThreadID() == device->threadid)) { | |
194 return; | |
195 } | |
196 SDL_mutexV(device->mixer_lock); | |
197 } | |
198 | |
199 | |
200 static void finalize_audio_entry_points(void) | |
201 { | |
202 /* | |
203 * Fill in stub functions for unused driver entry points. This lets us | |
204 * blindly call them without having to check for validity first. | |
205 */ | |
206 | |
207 #define FILL_STUB(x) \ | |
208 if (current_audio.impl.x == NULL) { \ | |
209 current_audio.impl.x = SDL_Audio##x##_Default; \ | |
210 } | |
211 FILL_STUB(DetectDevices); | |
212 FILL_STUB(GetDeviceName); | |
213 FILL_STUB(OpenDevice); | |
214 FILL_STUB(ThreadInit); | |
215 FILL_STUB(WaitDevice); | |
216 FILL_STUB(PlayDevice); | |
217 FILL_STUB(GetDeviceBuf); | |
218 FILL_STUB(WaitDone); | |
219 FILL_STUB(CloseDevice); | |
220 FILL_STUB(LockDevice); | |
221 FILL_STUB(UnlockDevice); | |
222 FILL_STUB(Deinitialize); | |
223 #undef FILL_STUB | |
224 } | |
225 | |
121 | 226 |
122 /* The general mixing thread function */ | 227 /* The general mixing thread function */ |
123 int SDLCALL | 228 int SDLCALL |
124 SDL_RunAudio(void *audiop) | 229 SDL_RunAudio(void *devicep) |
125 { | 230 { |
126 SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop; | 231 SDL_AudioDevice *device = (SDL_AudioDevice *) devicep; |
232 const int legacy_device = (device == open_devices[0]); | |
127 Uint8 *stream; | 233 Uint8 *stream; |
128 int stream_len; | 234 int stream_len; |
129 void *udata; | 235 void *udata; |
130 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len); | 236 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len); |
131 int silence; | 237 int silence; |
132 #if SDL_AUDIO_DRIVER_AHI | |
133 int started = 0; | |
134 | |
135 /* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */ | |
136 | |
137 D(bug("Task audio started audio struct:<%lx>...\n", audiop)); | |
138 | |
139 D(bug("Before Openaudio...")); | |
140 if (audio->OpenAudio(audio, &audio->spec) == -1) { | |
141 D(bug("Open audio failed...\n")); | |
142 return (-1); | |
143 } | |
144 D(bug("OpenAudio...OK\n")); | |
145 #endif | |
146 | 238 |
147 /* Perform any thread setup */ | 239 /* Perform any thread setup */ |
148 if (audio->ThreadInit) { | 240 device->threadid = SDL_ThreadID(); |
149 audio->ThreadInit(audio); | 241 current_audio.impl.ThreadInit(device); |
150 } | |
151 audio->threadid = SDL_ThreadID(); | |
152 | 242 |
153 /* Set up the mixing function */ | 243 /* Set up the mixing function */ |
154 fill = audio->spec.callback; | 244 fill = device->spec.callback; |
155 udata = audio->spec.userdata; | 245 udata = device->spec.userdata; |
156 | 246 |
157 #if SDL_AUDIO_DRIVER_AHI | 247 if (device->convert.needed) { |
158 audio_configured = 1; | 248 if (device->convert.src_format == AUDIO_U8) { |
159 | |
160 D(bug("Audio configured... Checking for conversion\n")); | |
161 SDL_mutexP(audio->mixer_lock); | |
162 D(bug("Semaphore obtained...\n")); | |
163 #endif | |
164 | |
165 if (audio->convert.needed) { | |
166 if (audio->convert.src_format == AUDIO_U8) { | |
167 silence = 0x80; | 249 silence = 0x80; |
168 } else { | 250 } else { |
169 silence = 0; | 251 silence = 0; |
170 } | 252 } |
171 stream_len = audio->convert.len; | 253 stream_len = device->convert.len; |
172 } else { | 254 } else { |
173 silence = audio->spec.silence; | 255 silence = device->spec.silence; |
174 stream_len = audio->spec.size; | 256 stream_len = device->spec.size; |
175 } | 257 } |
176 | |
177 #if SDL_AUDIO_DRIVER_AHI | |
178 SDL_mutexV(audio->mixer_lock); | |
179 D(bug("Entering audio loop...\n")); | |
180 #endif | |
181 | |
182 #ifdef __OS2__ | |
183 /* Increase the priority of this thread to make sure that | |
184 the audio will be continuous all the time! */ | |
185 #ifdef USE_DOSSETPRIORITY | |
186 if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) { | |
187 #ifdef DEBUG_BUILD | |
188 printf | |
189 ("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n", | |
190 SDL_ThreadID()); | |
191 #endif | |
192 DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); | |
193 } else { | |
194 #ifdef DEBUG_BUILD | |
195 printf | |
196 ("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", | |
197 SDL_ThreadID()); | |
198 #endif | |
199 DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0); | |
200 } | |
201 #endif | |
202 #endif | |
203 | 258 |
204 /* Loop, filling the audio buffers */ | 259 /* Loop, filling the audio buffers */ |
205 while (audio->enabled) { | 260 while (device->enabled) { |
206 | 261 |
207 /* Fill the current buffer with sound */ | 262 /* Fill the current buffer with sound */ |
208 if (audio->convert.needed) { | 263 if (device->convert.needed) { |
209 if (audio->convert.buf) { | 264 if (device->convert.buf) { |
210 stream = audio->convert.buf; | 265 stream = device->convert.buf; |
211 } else { | 266 } else { |
212 continue; | 267 continue; |
213 } | 268 } |
214 } else { | 269 } else { |
215 stream = audio->GetAudioBuf(audio); | 270 stream = current_audio.impl.GetDeviceBuf(device); |
216 if (stream == NULL) { | 271 if (stream == NULL) { |
217 stream = audio->fake_stream; | 272 stream = device->fake_stream; |
218 } | 273 } |
219 } | 274 } |
220 SDL_memset(stream, silence, stream_len); | 275 |
221 | 276 /* New code should fill buffer or set it to silence themselves. */ |
222 if (!audio->paused) { | 277 if (legacy_device) { |
223 SDL_mutexP(audio->mixer_lock); | 278 SDL_memset(stream, silence, stream_len); |
279 } | |
280 | |
281 if (!device->paused) { | |
282 SDL_mutexP(device->mixer_lock); | |
224 (*fill) (udata, stream, stream_len); | 283 (*fill) (udata, stream, stream_len); |
225 SDL_mutexV(audio->mixer_lock); | 284 SDL_mutexV(device->mixer_lock); |
226 } | 285 } |
227 | 286 |
228 /* Convert the audio if necessary */ | 287 /* Convert the audio if necessary */ |
229 if (audio->convert.needed) { | 288 if (device->convert.needed) { |
230 SDL_ConvertAudio(&audio->convert); | 289 SDL_ConvertAudio(&device->convert); |
231 stream = audio->GetAudioBuf(audio); | 290 stream = current_audio.impl.GetDeviceBuf(device); |
232 if (stream == NULL) { | 291 if (stream == NULL) { |
233 stream = audio->fake_stream; | 292 stream = device->fake_stream; |
234 } | 293 } |
235 SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt); | 294 SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt); |
236 } | 295 } |
237 | 296 |
238 /* Ready current buffer for play and change current buffer */ | 297 /* Ready current buffer for play and change current buffer */ |
239 if (stream != audio->fake_stream) { | 298 if (stream != device->fake_stream) { |
240 audio->PlayAudio(audio); | 299 current_audio.impl.PlayDevice(device); |
241 } | 300 } |
242 | 301 |
243 /* Wait for an audio buffer to become available */ | 302 /* Wait for an audio buffer to become available */ |
244 if (stream == audio->fake_stream) { | 303 if (stream == device->fake_stream) { |
245 SDL_Delay((audio->spec.samples * 1000) / audio->spec.freq); | 304 SDL_Delay((device->spec.samples * 1000) / device->spec.freq); |
246 } else { | 305 } else { |
247 audio->WaitAudio(audio); | 306 current_audio.impl.WaitDevice(device); |
248 } | 307 } |
249 } | 308 } |
250 | 309 |
251 /* Wait for the audio to drain.. */ | 310 /* Wait for the audio to drain.. */ |
252 if (audio->WaitDone) { | 311 current_audio.impl.WaitDone(device); |
253 audio->WaitDone(audio); | 312 |
254 } | |
255 #if SDL_AUDIO_DRIVER_AHI | |
256 D(bug("WaitAudio...Done\n")); | |
257 | |
258 audio->CloseAudio(audio); | |
259 | |
260 D(bug("CloseAudio..Done, subtask exiting...\n")); | |
261 audio_configured = 0; | |
262 #endif | |
263 #ifdef __OS2__ | |
264 #ifdef DEBUG_BUILD | |
265 printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID()); | |
266 #endif | |
267 #endif | |
268 return (0); | 313 return (0); |
269 } | 314 } |
270 | 315 |
271 static void | |
272 SDL_LockAudio_Default(SDL_AudioDevice * audio) | |
273 { | |
274 if (audio->thread && (SDL_ThreadID() == audio->threadid)) { | |
275 return; | |
276 } | |
277 SDL_mutexP(audio->mixer_lock); | |
278 } | |
279 | |
280 static void | |
281 SDL_UnlockAudio_Default(SDL_AudioDevice * audio) | |
282 { | |
283 if (audio->thread && (SDL_ThreadID() == audio->threadid)) { | |
284 return; | |
285 } | |
286 SDL_mutexV(audio->mixer_lock); | |
287 } | |
288 | 316 |
289 static SDL_AudioFormat | 317 static SDL_AudioFormat |
290 SDL_ParseAudioFormat(const char *string) | 318 SDL_ParseAudioFormat(const char *string) |
291 { | 319 { |
292 SDL_AudioFormat format = 0; | 320 #define CHECK_FMT_STRING(x) if (strcmp(string, #x) == 0) return AUDIO_##x |
293 | 321 CHECK_FMT_STRING(U8); |
294 switch (*string) { | 322 CHECK_FMT_STRING(S8); |
295 case 'U': | 323 CHECK_FMT_STRING(U16LSB); |
296 ++string; | 324 CHECK_FMT_STRING(S16LSB); |
297 format |= 0x0000; | 325 CHECK_FMT_STRING(U16MSB); |
298 break; | 326 CHECK_FMT_STRING(S16MSB); |
299 case 'S': | 327 CHECK_FMT_STRING(U16SYS); |
300 ++string; | 328 CHECK_FMT_STRING(S16SYS); |
301 format |= 0x8000; | 329 CHECK_FMT_STRING(U16); |
302 break; | 330 CHECK_FMT_STRING(S16); |
303 default: | 331 CHECK_FMT_STRING(S32LSB); |
304 return 0; | 332 CHECK_FMT_STRING(S32MSB); |
305 } | 333 CHECK_FMT_STRING(S32SYS); |
306 switch (SDL_atoi(string)) { | 334 CHECK_FMT_STRING(S32); |
307 case 8: | 335 CHECK_FMT_STRING(F32LSB); |
308 string += 1; | 336 CHECK_FMT_STRING(F32MSB); |
309 format |= 8; | 337 CHECK_FMT_STRING(F32SYS); |
310 break; | 338 CHECK_FMT_STRING(F32); |
311 case 16: | 339 #undef CHECK_FMT_STRING |
312 string += 2; | 340 return 0; |
313 format |= 16; | |
314 if (SDL_strcmp(string, "LSB") == 0 | |
315 #if SDL_BYTEORDER == SDL_LIL_ENDIAN | |
316 || SDL_strcmp(string, "SYS") == 0 | |
317 #endif | |
318 ) { | |
319 format |= 0x0000; | |
320 } | |
321 if (SDL_strcmp(string, "MSB") == 0 | |
322 #if SDL_BYTEORDER == SDL_BIG_ENDIAN | |
323 || SDL_strcmp(string, "SYS") == 0 | |
324 #endif | |
325 ) { | |
326 format |= 0x1000; | |
327 } | |
328 break; | |
329 default: | |
330 return 0; | |
331 } | |
332 return format; | |
333 } | 341 } |
334 | 342 |
335 int | 343 int |
336 SDL_GetNumAudioDrivers(void) | 344 SDL_GetNumAudioDrivers(void) |
337 { | 345 { |
348 } | 356 } |
349 | 357 |
350 int | 358 int |
351 SDL_AudioInit(const char *driver_name) | 359 SDL_AudioInit(const char *driver_name) |
352 { | 360 { |
353 SDL_AudioDevice *audio; | 361 int i = 0; |
354 int i = 0, idx; | 362 int initialized = 0; |
355 | 363 int tried_to_init = 0; |
356 /* Check to make sure we don't overwrite 'current_audio' */ | 364 |
357 if (current_audio != NULL) { | 365 if (SDL_WasInit(SDL_INIT_AUDIO)) { |
358 SDL_AudioQuit(); | 366 SDL_AudioQuit(); /* shutdown driver if already running. */ |
359 } | 367 } |
368 | |
369 SDL_memset(¤t_audio, '\0', sizeof (current_audio)); | |
370 SDL_memset(open_devices, '\0', sizeof (open_devices)); | |
360 | 371 |
361 /* Select the proper audio driver */ | 372 /* Select the proper audio driver */ |
362 audio = NULL; | |
363 idx = 0; | |
364 if (driver_name == NULL) { | 373 if (driver_name == NULL) { |
365 driver_name = SDL_getenv("SDL_AUDIODRIVER"); | 374 driver_name = SDL_getenv("SDL_AUDIODRIVER"); |
366 } | 375 } |
367 #if SDL_AUDIO_DRIVER_ESD | 376 |
368 if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) { | 377 for (i = 0; (!initialized) && (bootstrap[i]); ++i) { |
369 /* Ahem, we know that if ESPEAKER is set, user probably wants | 378 /* make sure we should even try this driver before doing so... */ |
370 to use ESD, but don't start it if it's not already running. | 379 const AudioBootStrap *backend = bootstrap[i]; |
371 This probably isn't the place to do this, but... Shh! :) | 380 if ( ((driver_name) && (SDL_strcasecmp(backend->name, driver_name))) || |
372 */ | 381 ((!driver_name) && (backend->demand_only)) ) { |
373 for (i = 0; bootstrap[i]; ++i) { | 382 continue; |
374 if (SDL_strcasecmp(bootstrap[i]->name, "esd") == 0) { | 383 } |
375 #ifdef HAVE_PUTENV | 384 |
376 const char *esd_no_spawn; | 385 tried_to_init = 1; |
377 | 386 SDL_memset(¤t_audio, 0, sizeof (current_audio)); |
378 /* Don't start ESD if it's not running */ | 387 current_audio.name = backend->name; |
379 esd_no_spawn = getenv("ESD_NO_SPAWN"); | 388 current_audio.desc = backend->desc; |
380 if (esd_no_spawn == NULL) { | 389 initialized = backend->init(¤t_audio.impl); |
381 putenv("ESD_NO_SPAWN=1"); | 390 } |
382 } | 391 |
383 #endif | 392 if (!initialized) { |
384 if (bootstrap[i]->available()) { | 393 /* specific drivers will set the error message if they fail... */ |
385 audio = bootstrap[i]->create(0); | 394 if (!tried_to_init) { |
386 break; | |
387 } | |
388 #ifdef HAVE_UNSETENV | |
389 if (esd_no_spawn == NULL) { | |
390 unsetenv("ESD_NO_SPAWN"); | |
391 } | |
392 #endif | |
393 } | |
394 } | |
395 } | |
396 #endif /* SDL_AUDIO_DRIVER_ESD */ | |
397 if (audio == NULL) { | |
398 if (driver_name != NULL) { | |
399 for (i = 0; bootstrap[i]; ++i) { | |
400 if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) { | |
401 if (bootstrap[i]->available()) { | |
402 audio = bootstrap[i]->create(idx); | |
403 } | |
404 break; | |
405 } | |
406 } | |
407 } else { | |
408 for (i = 0; bootstrap[i]; ++i) { | |
409 if (bootstrap[i]->available()) { | |
410 audio = bootstrap[i]->create(idx); | |
411 if (audio != NULL) { | |
412 break; | |
413 } | |
414 } | |
415 } | |
416 } | |
417 if (audio == NULL) { | |
418 if (driver_name) { | 395 if (driver_name) { |
419 SDL_SetError("%s not available", driver_name); | 396 SDL_SetError("%s not available", driver_name); |
420 } else { | 397 } else { |
421 SDL_SetError("No available audio device"); | 398 SDL_SetError("No available audio device"); |
422 } | 399 } |
423 #if 0 | 400 } |
424 /* Don't fail SDL_Init() if audio isn't available. | 401 |
425 SDL_OpenAudio() will handle it at that point. *sigh* | 402 SDL_memset(¤t_audio, 0, sizeof (current_audio)); |
426 */ | 403 return (-1); /* No driver was available, so fail. */ |
427 return (-1); | 404 } |
428 #endif | 405 |
429 } | 406 finalize_audio_entry_points(); |
430 } | 407 |
431 current_audio = audio; | |
432 if (current_audio) { | |
433 current_audio->name = bootstrap[i]->name; | |
434 if (!current_audio->LockAudio && !current_audio->UnlockAudio) { | |
435 current_audio->LockAudio = SDL_LockAudio_Default; | |
436 current_audio->UnlockAudio = SDL_UnlockAudio_Default; | |
437 } | |
438 } | |
439 return (0); | 408 return (0); |
440 } | 409 } |
441 | 410 |
442 /* | 411 /* |
443 * Get the current audio driver name | 412 * Get the current audio driver name |
444 */ | 413 */ |
445 const char * | 414 const char * |
446 SDL_GetCurrentAudioDriver() | 415 SDL_GetCurrentAudioDriver() |
447 { | 416 { |
448 if (current_audio) { | 417 return current_audio.name; |
449 return current_audio->name; | 418 } |
450 } | 419 |
451 return (NULL); | |
452 } | |
453 | 420 |
454 int | 421 int |
455 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained) | 422 SDL_GetNumAudioDevices(int iscapture) |
456 { | 423 { |
457 SDL_AudioDevice *audio; | 424 if (!SDL_WasInit(SDL_INIT_AUDIO)) { |
458 const char *env; | 425 return -1; |
459 | 426 } |
460 /* Start up the audio driver, if necessary */ | 427 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { |
461 if (!current_audio) { | 428 return 0; |
462 if ((SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) || | 429 } |
463 (current_audio == NULL)) { | 430 |
464 return (-1); | 431 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { |
465 } | 432 return 1; |
466 } | 433 } |
467 audio = current_audio; | 434 |
468 | 435 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { |
469 if (audio->opened) { | 436 return 1; |
470 SDL_SetError("Audio device is already opened"); | 437 } |
471 return (-1); | 438 |
472 } | 439 return current_audio.impl.DetectDevices(iscapture); |
473 | 440 } |
474 /* Verify some parameters */ | 441 |
475 if (desired->freq == 0) { | 442 |
476 env = SDL_getenv("SDL_AUDIO_FREQUENCY"); | 443 const char * |
477 if (env) { | 444 SDL_GetAudioDeviceName(int index, int iscapture) |
478 desired->freq = SDL_atoi(env); | 445 { |
479 } | 446 if (!SDL_WasInit(SDL_INIT_AUDIO)) { |
480 } | 447 SDL_SetError("Audio subsystem is not initialized"); |
481 if (desired->freq == 0) { | 448 return NULL; |
482 /* Pick some default audio frequency */ | 449 } |
483 desired->freq = 22050; | 450 |
484 } | 451 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { |
485 if (desired->format == 0) { | 452 SDL_SetError("No capture support"); |
486 env = SDL_getenv("SDL_AUDIO_FORMAT"); | 453 return NULL; |
487 if (env) { | 454 } |
488 desired->format = SDL_ParseAudioFormat(env); | 455 |
489 } | 456 if (index < 0) { |
490 } | 457 SDL_SetError("No such device"); |
491 if (desired->format == 0) { | 458 return NULL; |
492 /* Pick some default audio format */ | 459 } |
493 desired->format = AUDIO_S16; | 460 |
494 } | 461 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { |
495 if (desired->channels == 0) { | 462 return DEFAULT_INPUT_DEVNAME; |
496 env = SDL_getenv("SDL_AUDIO_CHANNELS"); | 463 } |
497 if (env) { | 464 |
498 desired->channels = (Uint8) SDL_atoi(env); | 465 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { |
499 } | 466 return DEFAULT_OUTPUT_DEVNAME; |
500 } | 467 } |
501 if (desired->channels == 0) { | 468 |
502 /* Pick a default number of channels */ | 469 return current_audio.impl.GetDeviceName(index, iscapture); |
503 desired->channels = 2; | 470 } |
504 } | 471 |
505 switch (desired->channels) { | 472 |
473 static void | |
474 close_audio_device(SDL_AudioDevice *device) | |
475 { | |
476 device->enabled = 0; | |
477 if (device->thread != NULL) { | |
478 SDL_WaitThread(device->thread, NULL); | |
479 } | |
480 if (device->mixer_lock != NULL) { | |
481 SDL_DestroyMutex(device->mixer_lock); | |
482 } | |
483 if (device->fake_stream != NULL) { | |
484 SDL_FreeAudioMem(device->fake_stream); | |
485 } | |
486 if (device->convert.needed) { | |
487 SDL_FreeAudioMem(device->convert.buf); | |
488 } | |
489 if (device->opened) { | |
490 current_audio.impl.CloseDevice(device); | |
491 device->opened = 0; | |
492 } | |
493 SDL_FreeAudioMem(device); | |
494 } | |
495 | |
496 | |
497 /* | |
498 * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig). | |
499 * Fills in a sanitized copy in (prepared). | |
500 * Returns non-zero if okay, zero on fatal parameters in (orig). | |
501 */ | |
502 static int | |
503 prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared) | |
504 { | |
505 SDL_memcpy(prepared, orig, sizeof (SDL_AudioSpec)); | |
506 | |
507 if (orig->callback == NULL) { | |
508 SDL_SetError("SDL_OpenAudio() passed a NULL callback"); | |
509 return 0; | |
510 } | |
511 | |
512 if (orig->freq == 0) { | |
513 const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY"); | |
514 if ( (!env) || ((prepared->freq = SDL_atoi(env)) == 0) ) { | |
515 prepared->freq = 22050; /* a reasonable default */ | |
516 } | |
517 } | |
518 | |
519 if (orig->format == 0) { | |
520 const char *env = SDL_getenv("SDL_AUDIO_FORMAT"); | |
521 if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) { | |
522 prepared->format = AUDIO_S16; /* a reasonable default */ | |
523 } | |
524 } | |
525 | |
526 switch (orig->channels) { | |
527 case 0: { | |
528 const char *env = SDL_getenv("SDL_AUDIO_CHANNELS"); | |
529 if ( (!env) || ((prepared->channels = SDL_atoi(env)) == 0) ) { | |
530 prepared->channels = 2; /* a reasonable default */ | |
531 } | |
532 break; | |
533 } | |
506 case 1: /* Mono */ | 534 case 1: /* Mono */ |
507 case 2: /* Stereo */ | 535 case 2: /* Stereo */ |
508 case 4: /* surround */ | 536 case 4: /* surround */ |
509 case 6: /* surround with center and lfe */ | 537 case 6: /* surround with center and lfe */ |
510 break; | 538 break; |
511 default: | 539 default: |
512 SDL_SetError("1 (mono) and 2 (stereo) channels supported"); | 540 SDL_SetError("Unsupported number of audio channels."); |
513 return (-1); | 541 return 0; |
514 } | 542 } |
515 if (desired->samples == 0) { | 543 |
516 env = SDL_getenv("SDL_AUDIO_SAMPLES"); | 544 if (orig->samples == 0) { |
517 if (env) { | 545 const char *env = SDL_getenv("SDL_AUDIO_SAMPLES"); |
518 desired->samples = (Uint16) SDL_atoi(env); | 546 if ( (!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0) ) { |
519 } | 547 /* Pick a default of ~46 ms at desired frequency */ |
520 } | 548 /* !!! FIXME: remove this when the non-Po2 resampling is in. */ |
521 if (desired->samples == 0) { | 549 const int samples = (prepared->freq / 1000) * 46; |
522 /* Pick a default of ~46 ms at desired frequency */ | 550 int power2 = 1; |
523 int samples = (desired->freq / 1000) * 46; | 551 while (power2 < samples) { |
524 int power2 = 1; | 552 power2 *= 2; |
525 while (power2 < samples) { | 553 } |
526 power2 *= 2; | 554 prepared->samples = power2; |
527 } | 555 } |
528 desired->samples = power2; | 556 } |
529 } | 557 |
530 if (desired->callback == NULL) { | 558 /* Calculate the silence and size of the audio specification */ |
531 SDL_SetError("SDL_OpenAudio() passed a NULL callback"); | 559 SDL_CalculateAudioSpec(prepared); |
532 return (-1); | 560 |
533 } | 561 return 1; |
534 #if defined(__MINT__) && SDL_THREADS_DISABLED | 562 } |
535 /* Uses interrupt driven audio, without thread */ | 563 |
536 #else | 564 |
565 static SDL_AudioDeviceID | |
566 open_audio_device(const char *devname, int iscapture, | |
567 const SDL_AudioSpec *_desired, SDL_AudioSpec *obtained, | |
568 int min_id) | |
569 { | |
570 SDL_AudioDeviceID id = 0; | |
571 SDL_AudioSpec desired; | |
572 SDL_AudioDevice *device; | |
573 int i = 0; | |
574 | |
575 if (!SDL_WasInit(SDL_INIT_AUDIO)) { | |
576 SDL_SetError("Audio subsystem is not initialized"); | |
577 return 0; | |
578 } | |
579 | |
580 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { | |
581 SDL_SetError("No capture support"); | |
582 return 0; | |
583 } | |
584 | |
585 if (!prepare_audiospec(_desired, &desired)) { | |
586 return 0; | |
587 } | |
588 | |
589 /* If app doesn't care about a specific device, let the user override. */ | |
590 if (devname == NULL) { | |
591 devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME"); | |
592 } | |
593 | |
594 /* | |
595 * Catch device names at the high level for the simple case... | |
596 * This lets us have a basic "device enumeration" for systems that | |
597 * don't have multiple devices, but makes sure the device name is | |
598 * always NULL when it hits the low level. | |
599 * | |
600 * Also make sure that the simple case prevents multiple simultaneous | |
601 * opens of the default system device. | |
602 */ | |
603 | |
604 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { | |
605 if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) { | |
606 SDL_SetError("No such device"); | |
607 return 0; | |
608 } | |
609 devname = NULL; | |
610 | |
611 for (i = 0; i < SDL_arraysize(open_devices); i++) { | |
612 if ((open_devices[i]) && (open_devices[i]->iscapture)) { | |
613 SDL_SetError("Audio device already open"); | |
614 return 0; | |
615 } | |
616 } | |
617 } | |
618 | |
619 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { | |
620 if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) { | |
621 SDL_SetError("No such device"); | |
622 return 0; | |
623 } | |
624 devname = NULL; | |
625 | |
626 for (i = 0; i < SDL_arraysize(open_devices); i++) { | |
627 if ((open_devices[i]) && (!open_devices[i]->iscapture)) { | |
628 SDL_SetError("Audio device already open"); | |
629 return 0; | |
630 } | |
631 } | |
632 } | |
633 | |
634 device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof (SDL_AudioDevice)); | |
635 if (device == NULL) { | |
636 SDL_OutOfMemory(); | |
637 return 0; | |
638 } | |
639 SDL_memset(device, '\0', sizeof (SDL_AudioDevice)); | |
640 SDL_memcpy(&device->spec, &desired, sizeof (SDL_AudioSpec)); | |
641 device->enabled = 1; | |
642 device->paused = 1; | |
643 device->iscapture = iscapture; | |
644 | |
537 /* Create a semaphore for locking the sound buffers */ | 645 /* Create a semaphore for locking the sound buffers */ |
538 audio->mixer_lock = SDL_CreateMutex(); | 646 if (!current_audio.impl.SkipMixerLock) { |
539 if (audio->mixer_lock == NULL) { | 647 device->mixer_lock = SDL_CreateMutex(); |
540 SDL_SetError("Couldn't create mixer lock"); | 648 if (device->mixer_lock == NULL) { |
541 SDL_CloseAudio(); | 649 close_audio_device(device); |
542 return (-1); | 650 SDL_SetError("Couldn't create mixer lock"); |
543 } | 651 return 0; |
544 #endif /* __MINT__ */ | 652 } |
545 | 653 } |
546 /* Calculate the silence and size of the audio specification */ | 654 |
547 SDL_CalculateAudioSpec(desired); | 655 if (!current_audio.impl.OpenDevice(device, devname, iscapture)) { |
548 | 656 close_audio_device(device); |
549 /* Open the audio subsystem */ | 657 return 0; |
550 SDL_memcpy(&audio->spec, desired, sizeof(audio->spec)); | 658 } |
551 audio->convert.needed = 0; | 659 device->opened = 1; |
552 audio->enabled = 1; | |
553 audio->paused = 1; | |
554 | |
555 #if !SDL_AUDIO_DRIVER_AHI | |
556 | |
557 /* AmigaOS opens audio inside the main loop */ | |
558 audio->opened = audio->OpenAudio(audio, &audio->spec) + 1; | |
559 | |
560 if (!audio->opened) { | |
561 SDL_CloseAudio(); | |
562 return (-1); | |
563 } | |
564 #else | |
565 D(bug("Locking semaphore...")); | |
566 SDL_mutexP(audio->mixer_lock); | |
567 | |
568 | |
569 audio->thread = SDL_CreateThread(SDL_RunAudio, audio); | |
570 D(bug("Created thread...\n")); | |
571 | |
572 if (audio->thread == NULL) { | |
573 SDL_mutexV(audio->mixer_lock); | |
574 SDL_CloseAudio(); | |
575 SDL_SetError("Couldn't create audio thread"); | |
576 return (-1); | |
577 } | |
578 | |
579 while (!audio_configured) | |
580 SDL_Delay(100); | |
581 #endif | |
582 | 660 |
583 /* If the audio driver changes the buffer size, accept it */ | 661 /* If the audio driver changes the buffer size, accept it */ |
584 if (audio->spec.samples != desired->samples) { | 662 if (device->spec.samples != desired.samples) { |
585 desired->samples = audio->spec.samples; | 663 desired.samples = device->spec.samples; |
586 SDL_CalculateAudioSpec(desired); | 664 SDL_CalculateAudioSpec(&device->spec); |
587 } | 665 } |
588 | 666 |
589 /* Allocate a fake audio memory buffer */ | 667 /* Allocate a fake audio memory buffer */ |
590 audio->fake_stream = SDL_AllocAudioMem(audio->spec.size); | 668 device->fake_stream = SDL_AllocAudioMem(device->spec.size); |
591 if (audio->fake_stream == NULL) { | 669 if (device->fake_stream == NULL) { |
592 SDL_CloseAudio(); | 670 close_audio_device(device); |
593 SDL_OutOfMemory(); | 671 SDL_OutOfMemory(); |
594 return (-1); | 672 return 0; |
595 } | 673 } |
596 | 674 |
597 /* See if we need to do any conversion */ | 675 /* See if we need to do any conversion */ |
598 if (obtained != NULL) { | 676 if (obtained != NULL) { |
599 SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec)); | 677 SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec)); |
600 } else if (desired->freq != audio->spec.freq || | 678 } else if (desired.freq != device->spec.freq || |
601 desired->format != audio->spec.format || | 679 desired.format != device->spec.format || |
602 desired->channels != audio->spec.channels) { | 680 desired.channels != device->spec.channels) { |
603 /* Build an audio conversion block */ | 681 /* Build an audio conversion block */ |
604 if (SDL_BuildAudioCVT(&audio->convert, | 682 if (SDL_BuildAudioCVT(&device->convert, |
605 desired->format, desired->channels, | 683 desired.format, desired.channels, |
606 desired->freq, | 684 desired.freq, |
607 audio->spec.format, audio->spec.channels, | 685 device->spec.format, device->spec.channels, |
608 audio->spec.freq) < 0) { | 686 device->spec.freq) < 0) { |
609 SDL_CloseAudio(); | 687 close_audio_device(device); |
610 return (-1); | 688 return 0; |
611 } | 689 } |
612 if (audio->convert.needed) { | 690 if (device->convert.needed) { |
613 audio->convert.len = desired->size; | 691 device->convert.len = desired.size; |
614 audio->convert.buf = | 692 device->convert.buf = |
615 (Uint8 *) SDL_AllocAudioMem(audio->convert.len * | 693 (Uint8 *) SDL_AllocAudioMem(device->convert.len * |
616 audio->convert.len_mult); | 694 device->convert.len_mult); |
617 if (audio->convert.buf == NULL) { | 695 if (device->convert.buf == NULL) { |
618 SDL_CloseAudio(); | 696 close_audio_device(device); |
619 SDL_OutOfMemory(); | 697 SDL_OutOfMemory(); |
620 return (-1); | 698 return 0; |
621 } | 699 } |
622 } | 700 } |
623 } | 701 } |
624 #if !SDL_AUDIO_DRIVER_AHI | 702 |
703 /* Find an available device ID and store the structure... */ | |
704 for (id = min_id-1; id < SDL_arraysize(open_devices); id++) { | |
705 if (open_devices[id] == NULL) { | |
706 open_devices[id] = device; | |
707 break; | |
708 } | |
709 } | |
710 | |
711 if (id == SDL_arraysize(open_devices)) { | |
712 SDL_SetError("Too many open audio devices"); | |
713 close_audio_device(device); | |
714 return 0; | |
715 } | |
716 | |
625 /* Start the audio thread if necessary */ | 717 /* Start the audio thread if necessary */ |
626 switch (audio->opened) { | 718 if (!current_audio.impl.ProvidesOwnCallbackThread) { |
627 case 1: | |
628 /* Start the audio thread */ | 719 /* Start the audio thread */ |
720 /* !!! FIXME: this is nasty. */ | |
629 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) | 721 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) |
630 #undef SDL_CreateThread | 722 #undef SDL_CreateThread |
631 audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL); | 723 device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL); |
632 #else | 724 #else |
633 audio->thread = SDL_CreateThread(SDL_RunAudio, audio); | 725 device->thread = SDL_CreateThread(SDL_RunAudio, device); |
634 #endif | 726 #endif |
635 if (audio->thread == NULL) { | 727 if (device->thread == NULL) { |
636 SDL_CloseAudio(); | 728 SDL_CloseAudioDevice(id+1); |
637 SDL_SetError("Couldn't create audio thread"); | 729 SDL_SetError("Couldn't create audio thread"); |
730 return 0; | |
731 } | |
732 } | |
733 | |
734 return id+1; | |
735 } | |
736 | |
737 | |
738 int | |
739 SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained) | |
740 { | |
741 SDL_AudioDeviceID id = 0; | |
742 | |
743 /* Start up the audio driver, if necessary. This is legacy behaviour! */ | |
744 if (!SDL_WasInit(SDL_INIT_AUDIO)) { | |
745 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { | |
638 return (-1); | 746 return (-1); |
639 } | 747 } |
640 break; | 748 } |
641 | 749 |
642 default: | 750 /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */ |
643 /* The audio is now playing */ | 751 if (open_devices[0] != NULL) { |
644 break; | 752 SDL_SetError("Audio device is already opened"); |
645 } | 753 return (-1); |
646 #else | 754 } |
647 SDL_mutexV(audio->mixer_lock); | 755 |
648 D(bug("SDL_OpenAudio USCITA...\n")); | 756 id = open_audio_device(NULL, 0, desired, obtained, 1); |
649 | 757 if (id > 1) { /* this should never happen in theory... */ |
650 #endif | 758 SDL_CloseAudioDevice(id); |
651 | 759 SDL_SetError("Internal error"); /* MUST be Device ID #1! */ |
652 return (0); | 760 return (-1); |
761 } | |
762 | |
763 return ((id == 0) ? -1 : 0); | |
764 } | |
765 | |
766 SDL_AudioDeviceID | |
767 SDL_OpenAudioDevice(const char *device, int iscapture, | |
768 const SDL_AudioSpec *desired, SDL_AudioSpec *obtained) | |
769 { | |
770 return open_audio_device(device, iscapture, desired, obtained, 2); | |
653 } | 771 } |
654 | 772 |
655 SDL_audiostatus | 773 SDL_audiostatus |
656 SDL_GetAudioStatus(void) | 774 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid) |
657 { | 775 { |
658 SDL_AudioDevice *audio = current_audio; | 776 SDL_AudioDevice *device = get_audio_device(devid); |
659 SDL_audiostatus status; | 777 SDL_audiostatus status = SDL_AUDIO_STOPPED; |
660 | 778 if (device && device->enabled) { |
661 status = SDL_AUDIO_STOPPED; | 779 if (device->paused) { |
662 if (audio && audio->enabled) { | |
663 if (audio->paused) { | |
664 status = SDL_AUDIO_PAUSED; | 780 status = SDL_AUDIO_PAUSED; |
665 } else { | 781 } else { |
666 status = SDL_AUDIO_PLAYING; | 782 status = SDL_AUDIO_PLAYING; |
667 } | 783 } |
668 } | 784 } |
669 return (status); | 785 return (status); |
670 } | 786 } |
671 | 787 |
788 | |
789 SDL_audiostatus | |
790 SDL_GetAudioStatus(void) | |
791 { | |
792 return SDL_GetAudioDeviceStatus(1); | |
793 } | |
794 | |
795 void | |
796 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on) | |
797 { | |
798 SDL_AudioDevice *device = get_audio_device(devid); | |
799 if (device) { | |
800 device->paused = pause_on; | |
801 } | |
802 } | |
803 | |
672 void | 804 void |
673 SDL_PauseAudio(int pause_on) | 805 SDL_PauseAudio(int pause_on) |
674 { | 806 { |
675 SDL_AudioDevice *audio = current_audio; | 807 SDL_PauseAudioDevice(1, pause_on); |
676 | 808 } |
677 if (audio) { | 809 |
678 audio->paused = pause_on; | 810 |
811 void | |
812 SDL_LockAudioDevice(SDL_AudioDeviceID devid) | |
813 { | |
814 /* Obtain a lock on the mixing buffers */ | |
815 SDL_AudioDevice *device = get_audio_device(devid); | |
816 if (device) { | |
817 current_audio.impl.LockDevice(device); | |
679 } | 818 } |
680 } | 819 } |
681 | 820 |
682 void | 821 void |
683 SDL_LockAudio(void) | 822 SDL_LockAudio(void) |
684 { | 823 { |
685 SDL_AudioDevice *audio = current_audio; | 824 SDL_LockAudioDevice(1); |
686 | 825 } |
826 | |
827 void | |
828 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid) | |
829 { | |
687 /* Obtain a lock on the mixing buffers */ | 830 /* Obtain a lock on the mixing buffers */ |
688 if (audio && audio->LockAudio) { | 831 SDL_AudioDevice *device = get_audio_device(devid); |
689 audio->LockAudio(audio); | 832 if (device) { |
833 current_audio.impl.UnlockDevice(device); | |
690 } | 834 } |
691 } | 835 } |
692 | 836 |
693 void | 837 void |
694 SDL_UnlockAudio(void) | 838 SDL_UnlockAudio(void) |
695 { | 839 { |
696 SDL_AudioDevice *audio = current_audio; | 840 SDL_UnlockAudioDevice(1); |
697 | 841 } |
698 /* Release lock on the mixing buffers */ | 842 |
699 if (audio && audio->UnlockAudio) { | 843 void |
700 audio->UnlockAudio(audio); | 844 SDL_CloseAudioDevice(SDL_AudioDeviceID devid) |
845 { | |
846 SDL_AudioDevice *device = get_audio_device(devid); | |
847 if (device) { | |
848 close_audio_device(device); | |
849 open_devices[devid-1] = NULL; | |
701 } | 850 } |
702 } | 851 } |
703 | 852 |
704 void | 853 void |
705 SDL_CloseAudio(void) | 854 SDL_CloseAudio(void) |
706 { | 855 { |
707 SDL_QuitSubSystem(SDL_INIT_AUDIO); | 856 SDL_CloseAudioDevice(1); |
708 } | 857 } |
709 | 858 |
710 void | 859 void |
711 SDL_AudioQuit(void) | 860 SDL_AudioQuit(void) |
712 { | 861 { |
713 SDL_AudioDevice *audio = current_audio; | 862 SDL_AudioDeviceID i; |
714 | 863 for (i = 0; i < SDL_arraysize(open_devices); i++) { |
715 if (audio) { | 864 SDL_CloseAudioDevice(i); |
716 audio->enabled = 0; | 865 } |
717 if (audio->thread != NULL) { | 866 |
718 SDL_WaitThread(audio->thread, NULL); | 867 /* Free the driver data */ |
719 } | 868 current_audio.impl.Deinitialize(); |
720 if (audio->mixer_lock != NULL) { | 869 SDL_memset(¤t_audio, '\0', sizeof (current_audio)); |
721 SDL_DestroyMutex(audio->mixer_lock); | 870 SDL_memset(open_devices, '\0', sizeof (open_devices)); |
722 } | |
723 if (audio->fake_stream != NULL) { | |
724 SDL_FreeAudioMem(audio->fake_stream); | |
725 } | |
726 if (audio->convert.needed) { | |
727 SDL_FreeAudioMem(audio->convert.buf); | |
728 | |
729 } | |
730 #if !SDL_AUDIO_DRIVER_AHI | |
731 if (audio->opened) { | |
732 audio->CloseAudio(audio); | |
733 audio->opened = 0; | |
734 } | |
735 #endif | |
736 /* Free the driver data */ | |
737 audio->free(audio); | |
738 current_audio = NULL; | |
739 } | |
740 } | 871 } |
741 | 872 |
742 #define NUM_FORMATS 10 | 873 #define NUM_FORMATS 10 |
743 static int format_idx; | 874 static int format_idx; |
744 static int format_idx_sub; | 875 static int format_idx_sub; |
795 break; | 926 break; |
796 default: | 927 default: |
797 spec->silence = 0x00; | 928 spec->silence = 0x00; |
798 break; | 929 break; |
799 } | 930 } |
800 spec->size = (spec->format & 0xFF) / 8; | 931 spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8; |
801 spec->size *= spec->channels; | 932 spec->size *= spec->channels; |
802 spec->size *= spec->samples; | 933 spec->size *= spec->samples; |
803 } | 934 } |
804 | 935 |
936 | |
937 /* | |
938 * Moved here from SDL_mixer.c, since it relies on internals of an opened | |
939 * audio device (and is deprecated, by the way!). | |
940 */ | |
941 void | |
942 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume) | |
943 { | |
944 /* Mix the user-level audio format */ | |
945 SDL_AudioDevice *device = get_audio_device(1); | |
946 if (device != NULL) { | |
947 SDL_AudioFormat format; | |
948 if (device->convert.needed) { | |
949 format = device->convert.src_format; | |
950 } else { | |
951 format = device->spec.format; | |
952 } | |
953 SDL_MixAudioFormat(dst, src, format, len, volume); | |
954 } | |
955 } | |
956 | |
805 /* vi: set ts=4 sw=4 expandtab: */ | 957 /* vi: set ts=4 sw=4 expandtab: */ |