Mercurial > sdl-ios-xcode
annotate src/audio/windx5/SDL_dx5audio.c @ 4389:c6c3a6e7db46 SDL-1.2
Fixed bug #899
Jeremiah Morris 2009-12-09 16:23:50 PST
Re-enable mouseLocation workaround on 10.4, 10.5
OS X systems before 10.6 have a bug with [NSEvent mouseLocation] if the screen
resolution changes. SDL_QuartzVideo.m contains a workaround for this bug, but
it was placed inside an #ifdef in revision 4762. The comment reads, "I'm
gambling they fixed this by 10.4."
After seeing this bug on several Tiger and Leopard systems (both PPC and
Intel), I can confirm that it's not fixed until 10.6. The workaround doesn't
compile for x86_64/10.6, so I can understand why it was segregated, but it
needs to remain in place for the i386 and ppc versions. The workaround causes
no problems under 10.6, even though it's not necessary there.
Patch is attached with one method of keeping the workaround active on the
systems that need it.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 11 Dec 2009 15:11:49 +0000 |
parents | a1b03ba2fcd0 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
4159 | 3 Copyright (C) 1997-2009 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
217
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
22 #include "SDL_config.h" |
0 | 23 |
24 /* Allow access to a raw mixing buffer */ | |
25 | |
26 #include "SDL_timer.h" | |
27 #include "SDL_audio.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
28 #include "../SDL_audio_c.h" |
0 | 29 #include "SDL_dx5audio.h" |
30 | |
31 /* Define this if you want to use DirectX 6 DirectSoundNotify interface */ | |
32 //#define USE_POSITION_NOTIFY | |
33 | |
34 /* DirectX function pointers for audio */ | |
35 HRESULT (WINAPI *DSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN); | |
36 | |
37 /* Audio driver functions */ | |
38 static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
39 static void DX5_ThreadInit(_THIS); | |
40 static void DX5_WaitAudio_BusyWait(_THIS); | |
41 #ifdef USE_POSITION_NOTIFY | |
42 static void DX6_WaitAudio_EventWait(_THIS); | |
43 #endif | |
44 static void DX5_PlayAudio(_THIS); | |
45 static Uint8 *DX5_GetAudioBuf(_THIS); | |
46 static void DX5_WaitDone(_THIS); | |
47 static void DX5_CloseAudio(_THIS); | |
48 | |
49 /* Audio driver bootstrap functions */ | |
50 | |
51 static int Audio_Available(void) | |
52 { | |
53 HINSTANCE DSoundDLL; | |
54 int dsound_ok; | |
55 | |
56 /* Version check DSOUND.DLL (Is DirectX okay?) */ | |
57 dsound_ok = 0; | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
58 DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); |
0 | 59 if ( DSoundDLL != NULL ) { |
60 /* We just use basic DirectSound, we're okay */ | |
61 /* Yay! */ | |
62 /* Unfortunately, the sound drivers on NT have | |
63 higher latencies than the audio buffers used | |
64 by many SDL applications, so there are gaps | |
65 in the audio - it sounds terrible. Punt for now. | |
66 */ | |
67 OSVERSIONINFO ver; | |
68 ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); | |
69 GetVersionEx(&ver); | |
70 switch (ver.dwPlatformId) { | |
71 case VER_PLATFORM_WIN32_NT: | |
72 if ( ver.dwMajorVersion > 4 ) { | |
73 /* Win2K */ | |
74 dsound_ok = 1; | |
75 } else { | |
76 /* WinNT */ | |
77 dsound_ok = 0; | |
78 } | |
79 break; | |
80 default: | |
81 /* Win95 or Win98 */ | |
82 dsound_ok = 1; | |
83 break; | |
84 } | |
85 /* Now check for DirectX 5 or better - otherwise | |
86 * we will fail later in DX5_OpenAudio without a chance | |
87 * to fall back to the DIB driver. */ | |
88 if (dsound_ok) { | |
89 /* DirectSoundCaptureCreate was added in DX5 */ | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
90 if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) |
0 | 91 dsound_ok = 0; |
92 | |
93 } | |
94 /* Clean up.. */ | |
95 FreeLibrary(DSoundDLL); | |
96 } | |
97 return(dsound_ok); | |
98 } | |
99 | |
100 /* Functions for loading the DirectX functions dynamically */ | |
101 static HINSTANCE DSoundDLL = NULL; | |
102 | |
103 static void DX5_Unload(void) | |
104 { | |
105 if ( DSoundDLL != NULL ) { | |
106 FreeLibrary(DSoundDLL); | |
107 DSoundCreate = NULL; | |
108 DSoundDLL = NULL; | |
109 } | |
110 } | |
111 static int DX5_Load(void) | |
112 { | |
113 int status; | |
114 | |
115 DX5_Unload(); | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
116 DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); |
0 | 117 if ( DSoundDLL != NULL ) { |
118 DSoundCreate = (void *)GetProcAddress(DSoundDLL, | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
119 TEXT("DirectSoundCreate")); |
0 | 120 } |
121 if ( DSoundDLL && DSoundCreate ) { | |
122 status = 0; | |
123 } else { | |
124 DX5_Unload(); | |
125 status = -1; | |
126 } | |
127 return status; | |
128 } | |
129 | |
130 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
131 { | |
132 DX5_Unload(); | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
133 SDL_free(device->hidden); |
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
134 SDL_free(device); |
0 | 135 } |
136 | |
137 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
138 { | |
139 SDL_AudioDevice *this; | |
140 | |
141 /* Load DirectX */ | |
142 if ( DX5_Load() < 0 ) { | |
143 return(NULL); | |
144 } | |
145 | |
146 /* Initialize all variables that we clean on shutdown */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
147 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); |
0 | 148 if ( this ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
149 SDL_memset(this, 0, (sizeof *this)); |
0 | 150 this->hidden = (struct SDL_PrivateAudioData *) |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
151 SDL_malloc((sizeof *this->hidden)); |
0 | 152 } |
153 if ( (this == NULL) || (this->hidden == NULL) ) { | |
154 SDL_OutOfMemory(); | |
155 if ( this ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
156 SDL_free(this); |
0 | 157 } |
158 return(0); | |
159 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
160 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
0 | 161 |
162 /* Set the function pointers */ | |
163 this->OpenAudio = DX5_OpenAudio; | |
164 this->ThreadInit = DX5_ThreadInit; | |
165 this->WaitAudio = DX5_WaitAudio_BusyWait; | |
166 this->PlayAudio = DX5_PlayAudio; | |
167 this->GetAudioBuf = DX5_GetAudioBuf; | |
168 this->WaitDone = DX5_WaitDone; | |
169 this->CloseAudio = DX5_CloseAudio; | |
170 | |
171 this->free = Audio_DeleteDevice; | |
172 | |
173 return this; | |
174 } | |
175 | |
176 AudioBootStrap DSOUND_bootstrap = { | |
177 "dsound", "Win95/98/2000 DirectSound", | |
178 Audio_Available, Audio_CreateDevice | |
179 }; | |
180 | |
181 static void SetDSerror(const char *function, int code) | |
182 { | |
183 static const char *error; | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
184 static char errbuf[1024]; |
0 | 185 |
186 errbuf[0] = 0; | |
187 switch (code) { | |
188 case E_NOINTERFACE: | |
189 error = | |
190 "Unsupported interface\n-- Is DirectX 5.0 or later installed?"; | |
191 break; | |
192 case DSERR_ALLOCATED: | |
193 error = "Audio device in use"; | |
194 break; | |
195 case DSERR_BADFORMAT: | |
196 error = "Unsupported audio format"; | |
197 break; | |
198 case DSERR_BUFFERLOST: | |
199 error = "Mixing buffer was lost"; | |
200 break; | |
201 case DSERR_CONTROLUNAVAIL: | |
202 error = "Control requested is not available"; | |
203 break; | |
204 case DSERR_INVALIDCALL: | |
205 error = "Invalid call for the current state"; | |
206 break; | |
207 case DSERR_INVALIDPARAM: | |
208 error = "Invalid parameter"; | |
209 break; | |
210 case DSERR_NODRIVER: | |
211 error = "No audio device found"; | |
212 break; | |
213 case DSERR_OUTOFMEMORY: | |
214 error = "Out of memory"; | |
215 break; | |
216 case DSERR_PRIOLEVELNEEDED: | |
217 error = "Caller doesn't have priority"; | |
218 break; | |
219 case DSERR_UNSUPPORTED: | |
220 error = "Function not supported"; | |
221 break; | |
222 default: | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
223 SDL_snprintf(errbuf, SDL_arraysize(errbuf), |
1330
450721ad5436
It's now possible to build SDL without any C runtime at all on Windows,
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
224 "%s: Unknown DirectSound error: 0x%x", |
0 | 225 function, code); |
226 break; | |
227 } | |
228 if ( ! errbuf[0] ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
229 SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); |
0 | 230 } |
231 SDL_SetError("%s", errbuf); | |
232 return; | |
233 } | |
234 | |
235 /* DirectSound needs to be associated with a window */ | |
236 static HWND mainwin = NULL; | |
237 /* */ | |
238 void DX5_SoundFocus(HWND hwnd) | |
239 { | |
240 mainwin = hwnd; | |
241 } | |
242 | |
243 static void DX5_ThreadInit(_THIS) | |
244 { | |
245 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); | |
246 } | |
247 | |
248 static void DX5_WaitAudio_BusyWait(_THIS) | |
249 { | |
250 DWORD status; | |
251 DWORD cursor, junk; | |
252 HRESULT result; | |
253 | |
254 /* Semi-busy wait, since we have no way of getting play notification | |
255 on a primary mixing buffer located in hardware (DirectX 5.0) | |
256 */ | |
1877 | 257 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor); |
0 | 258 if ( result != DS_OK ) { |
259 if ( result == DSERR_BUFFERLOST ) { | |
260 IDirectSoundBuffer_Restore(mixbuf); | |
261 } | |
262 #ifdef DEBUG_SOUND | |
263 SetDSerror("DirectSound GetCurrentPosition", result); | |
264 #endif | |
265 return; | |
266 } | |
267 | |
1877 | 268 while ( (cursor/mixlen) == lastchunk ) { |
0 | 269 /* FIXME: find out how much time is left and sleep that long */ |
1877 | 270 SDL_Delay(1); |
0 | 271 |
272 /* Try to restore a lost sound buffer */ | |
273 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
274 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
275 IDirectSoundBuffer_Restore(mixbuf); | |
276 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
277 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
278 break; | |
279 } | |
280 } | |
281 if ( ! (status&DSBSTATUS_PLAYING) ) { | |
282 result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); | |
283 if ( result == DS_OK ) { | |
284 continue; | |
285 } | |
286 #ifdef DEBUG_SOUND | |
287 SetDSerror("DirectSound Play", result); | |
288 #endif | |
289 return; | |
290 } | |
291 | |
292 /* Find out where we are playing */ | |
293 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, | |
1877 | 294 &junk, &cursor); |
0 | 295 if ( result != DS_OK ) { |
296 SetDSerror("DirectSound GetCurrentPosition", result); | |
297 return; | |
298 } | |
299 } | |
300 } | |
301 | |
302 #ifdef USE_POSITION_NOTIFY | |
303 static void DX6_WaitAudio_EventWait(_THIS) | |
304 { | |
305 DWORD status; | |
306 HRESULT result; | |
307 | |
308 /* Try to restore a lost sound buffer */ | |
309 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
310 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
311 IDirectSoundBuffer_Restore(mixbuf); | |
312 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
313 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
314 return; | |
315 } | |
316 } | |
317 if ( ! (status&DSBSTATUS_PLAYING) ) { | |
318 result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); | |
319 if ( result != DS_OK ) { | |
320 #ifdef DEBUG_SOUND | |
321 SetDSerror("DirectSound Play", result); | |
322 #endif | |
323 return; | |
324 } | |
325 } | |
326 WaitForSingleObject(audio_event, INFINITE); | |
327 } | |
328 #endif /* USE_POSITION_NOTIFY */ | |
329 | |
330 static void DX5_PlayAudio(_THIS) | |
331 { | |
332 /* Unlock the buffer, allowing it to play */ | |
333 if ( locked_buf ) { | |
334 IDirectSoundBuffer_Unlock(mixbuf, locked_buf, mixlen, NULL, 0); | |
335 } | |
336 | |
337 } | |
338 | |
339 static Uint8 *DX5_GetAudioBuf(_THIS) | |
340 { | |
341 DWORD cursor, junk; | |
342 HRESULT result; | |
343 DWORD rawlen; | |
344 | |
345 /* Figure out which blocks to fill next */ | |
346 locked_buf = NULL; | |
1877 | 347 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor); |
0 | 348 if ( result == DSERR_BUFFERLOST ) { |
349 IDirectSoundBuffer_Restore(mixbuf); | |
350 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, | |
1877 | 351 &junk, &cursor); |
0 | 352 } |
353 if ( result != DS_OK ) { | |
354 SetDSerror("DirectSound GetCurrentPosition", result); | |
355 return(NULL); | |
356 } | |
357 cursor /= mixlen; | |
1877 | 358 #ifdef DEBUG_SOUND |
359 /* Detect audio dropouts */ | |
360 { DWORD spot = cursor; | |
361 if ( spot < lastchunk ) { | |
362 spot += NUM_BUFFERS; | |
363 } | |
364 if ( spot > lastchunk+1 ) { | |
365 fprintf(stderr, "Audio dropout, missed %d fragments\n", | |
366 (spot - (lastchunk+1))); | |
367 } | |
368 } | |
369 #endif | |
370 lastchunk = cursor; | |
0 | 371 cursor = (cursor+1)%NUM_BUFFERS; |
372 cursor *= mixlen; | |
373 | |
374 /* Lock the audio buffer */ | |
375 result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, | |
376 (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); | |
377 if ( result == DSERR_BUFFERLOST ) { | |
378 IDirectSoundBuffer_Restore(mixbuf); | |
379 result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, | |
380 (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); | |
381 } | |
382 if ( result != DS_OK ) { | |
383 SetDSerror("DirectSound Lock", result); | |
384 return(NULL); | |
385 } | |
386 return(locked_buf); | |
387 } | |
388 | |
389 static void DX5_WaitDone(_THIS) | |
390 { | |
391 Uint8 *stream; | |
392 | |
393 /* Wait for the playing chunk to finish */ | |
394 stream = this->GetAudioBuf(this); | |
395 if ( stream != NULL ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
396 SDL_memset(stream, silence, mixlen); |
0 | 397 this->PlayAudio(this); |
398 } | |
399 this->WaitAudio(this); | |
400 | |
401 /* Stop the looping sound buffer */ | |
402 IDirectSoundBuffer_Stop(mixbuf); | |
403 } | |
404 | |
405 static void DX5_CloseAudio(_THIS) | |
406 { | |
407 if ( sound != NULL ) { | |
408 if ( mixbuf != NULL ) { | |
409 /* Clean up the audio buffer */ | |
410 IDirectSoundBuffer_Release(mixbuf); | |
411 mixbuf = NULL; | |
412 } | |
413 if ( audio_event != NULL ) { | |
414 CloseHandle(audio_event); | |
415 audio_event = NULL; | |
416 } | |
417 IDirectSound_Release(sound); | |
418 sound = NULL; | |
419 } | |
420 } | |
421 | |
469 | 422 #ifdef USE_PRIMARY_BUFFER |
0 | 423 /* This function tries to create a primary audio buffer, and returns the |
424 number of audio chunks available in the created buffer. | |
425 */ | |
426 static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, | |
427 LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) | |
428 { | |
429 HRESULT result; | |
430 DSBUFFERDESC format; | |
431 DSBCAPS caps; | |
432 int numchunks; | |
433 | |
434 /* Try to set primary mixing privileges */ | |
435 result = IDirectSound_SetCooperativeLevel(sndObj, focus, | |
436 DSSCL_WRITEPRIMARY); | |
437 if ( result != DS_OK ) { | |
438 #ifdef DEBUG_SOUND | |
439 SetDSerror("DirectSound SetCooperativeLevel", result); | |
440 #endif | |
441 return(-1); | |
442 } | |
443 | |
444 /* Try to create the primary buffer */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
445 SDL_memset(&format, 0, sizeof(format)); |
0 | 446 format.dwSize = sizeof(format); |
447 format.dwFlags=(DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2); | |
217
add626b825bb
Use the sticky focus flag so audio isn't muted when application is switched.
Sam Lantinga <slouken@libsdl.org>
parents:
118
diff
changeset
|
448 format.dwFlags |= DSBCAPS_STICKYFOCUS; |
0 | 449 #ifdef USE_POSITION_NOTIFY |
450 format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; | |
451 #endif | |
452 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); | |
453 if ( result != DS_OK ) { | |
454 #ifdef DEBUG_SOUND | |
455 SetDSerror("DirectSound CreateSoundBuffer", result); | |
456 #endif | |
457 return(-1); | |
458 } | |
459 | |
460 /* Check the size of the fragment buffer */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
461 SDL_memset(&caps, 0, sizeof(caps)); |
0 | 462 caps.dwSize = sizeof(caps); |
463 result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); | |
464 if ( result != DS_OK ) { | |
465 #ifdef DEBUG_SOUND | |
466 SetDSerror("DirectSound GetCaps", result); | |
467 #endif | |
468 IDirectSoundBuffer_Release(*sndbuf); | |
469 return(-1); | |
470 } | |
471 if ( (chunksize > caps.dwBufferBytes) || | |
472 ((caps.dwBufferBytes%chunksize) != 0) ) { | |
473 /* The primary buffer size is not a multiple of 'chunksize' | |
474 -- this hopefully doesn't happen when 'chunksize' is a | |
475 power of 2. | |
476 */ | |
477 IDirectSoundBuffer_Release(*sndbuf); | |
478 SDL_SetError( | |
479 "Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", | |
480 caps.dwBufferBytes, chunksize); | |
481 return(-1); | |
482 } | |
483 numchunks = (caps.dwBufferBytes/chunksize); | |
484 | |
485 /* Set the primary audio format */ | |
486 result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); | |
487 if ( result != DS_OK ) { | |
488 #ifdef DEBUG_SOUND | |
489 SetDSerror("DirectSound SetFormat", result); | |
490 #endif | |
491 IDirectSoundBuffer_Release(*sndbuf); | |
492 return(-1); | |
493 } | |
494 return(numchunks); | |
495 } | |
469 | 496 #endif /* USE_PRIMARY_BUFFER */ |
0 | 497 |
498 /* This function tries to create a secondary audio buffer, and returns the | |
499 number of audio chunks available in the created buffer. | |
500 */ | |
501 static int CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, | |
502 LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) | |
503 { | |
1877 | 504 const int numchunks = 8; |
0 | 505 HRESULT result; |
506 DSBUFFERDESC format; | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
507 LPVOID pvAudioPtr1, pvAudioPtr2; |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
508 DWORD dwAudioBytes1, dwAudioBytes2; |
0 | 509 |
510 /* Try to set primary mixing privileges */ | |
511 if ( focus ) { | |
512 result = IDirectSound_SetCooperativeLevel(sndObj, | |
513 focus, DSSCL_PRIORITY); | |
514 } else { | |
515 result = IDirectSound_SetCooperativeLevel(sndObj, | |
516 GetDesktopWindow(), DSSCL_NORMAL); | |
517 } | |
518 if ( result != DS_OK ) { | |
519 #ifdef DEBUG_SOUND | |
520 SetDSerror("DirectSound SetCooperativeLevel", result); | |
521 #endif | |
522 return(-1); | |
523 } | |
524 | |
525 /* Try to create the secondary buffer */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
526 SDL_memset(&format, 0, sizeof(format)); |
0 | 527 format.dwSize = sizeof(format); |
528 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2; | |
529 #ifdef USE_POSITION_NOTIFY | |
530 format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; | |
531 #endif | |
532 if ( ! focus ) { | |
533 format.dwFlags |= DSBCAPS_GLOBALFOCUS; | |
217
add626b825bb
Use the sticky focus flag so audio isn't muted when application is switched.
Sam Lantinga <slouken@libsdl.org>
parents:
118
diff
changeset
|
534 } else { |
add626b825bb
Use the sticky focus flag so audio isn't muted when application is switched.
Sam Lantinga <slouken@libsdl.org>
parents:
118
diff
changeset
|
535 format.dwFlags |= DSBCAPS_STICKYFOCUS; |
0 | 536 } |
537 format.dwBufferBytes = numchunks*chunksize; | |
538 if ( (format.dwBufferBytes < DSBSIZE_MIN) || | |
539 (format.dwBufferBytes > DSBSIZE_MAX) ) { | |
540 SDL_SetError("Sound buffer size must be between %d and %d", | |
541 DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks); | |
542 return(-1); | |
543 } | |
544 format.dwReserved = 0; | |
545 format.lpwfxFormat = wavefmt; | |
546 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); | |
547 if ( result != DS_OK ) { | |
548 SetDSerror("DirectSound CreateSoundBuffer", result); | |
549 return(-1); | |
550 } | |
551 IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); | |
552 | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
553 /* Silence the initial audio buffer */ |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
554 result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
555 (LPVOID *)&pvAudioPtr1, &dwAudioBytes1, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
556 (LPVOID *)&pvAudioPtr2, &dwAudioBytes2, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
557 DSBLOCK_ENTIREBUFFER); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
558 if ( result == DS_OK ) { |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
559 if ( wavefmt->wBitsPerSample == 8 ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
560 SDL_memset(pvAudioPtr1, 0x80, dwAudioBytes1); |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
561 } else { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
562 SDL_memset(pvAudioPtr1, 0x00, dwAudioBytes1); |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
563 } |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
564 IDirectSoundBuffer_Unlock(*sndbuf, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
565 (LPVOID)pvAudioPtr1, dwAudioBytes1, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
566 (LPVOID)pvAudioPtr2, dwAudioBytes2); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
567 } |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
568 |
0 | 569 /* We're ready to go */ |
570 return(numchunks); | |
571 } | |
572 | |
573 /* This function tries to set position notify events on the mixing buffer */ | |
574 #ifdef USE_POSITION_NOTIFY | |
575 static int CreateAudioEvent(_THIS) | |
576 { | |
577 LPDIRECTSOUNDNOTIFY notify; | |
578 DSBPOSITIONNOTIFY *notify_positions; | |
579 int i, retval; | |
580 HRESULT result; | |
581 | |
582 /* Default to fail on exit */ | |
583 retval = -1; | |
584 notify = NULL; | |
585 | |
586 /* Query for the interface */ | |
587 result = IDirectSoundBuffer_QueryInterface(mixbuf, | |
588 &IID_IDirectSoundNotify, (void *)¬ify); | |
589 if ( result != DS_OK ) { | |
590 goto done; | |
591 } | |
592 | |
593 /* Allocate the notify structures */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
594 notify_positions = (DSBPOSITIONNOTIFY *)SDL_malloc(NUM_BUFFERS* |
0 | 595 sizeof(*notify_positions)); |
596 if ( notify_positions == NULL ) { | |
597 goto done; | |
598 } | |
599 | |
600 /* Create the notify event */ | |
601 audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); | |
602 if ( audio_event == NULL ) { | |
603 goto done; | |
604 } | |
605 | |
606 /* Set up the notify structures */ | |
607 for ( i=0; i<NUM_BUFFERS; ++i ) { | |
608 notify_positions[i].dwOffset = i*mixlen; | |
609 notify_positions[i].hEventNotify = audio_event; | |
610 } | |
611 result = IDirectSoundNotify_SetNotificationPositions(notify, | |
612 NUM_BUFFERS, notify_positions); | |
613 if ( result == DS_OK ) { | |
614 retval = 0; | |
615 } | |
616 done: | |
617 if ( notify != NULL ) { | |
618 IDirectSoundNotify_Release(notify); | |
619 } | |
620 return(retval); | |
621 } | |
622 #endif /* USE_POSITION_NOTIFY */ | |
623 | |
624 static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
625 { | |
626 HRESULT result; | |
627 WAVEFORMATEX waveformat; | |
628 | |
629 /* Set basic WAVE format parameters */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
630 SDL_memset(&waveformat, 0, sizeof(waveformat)); |
0 | 631 waveformat.wFormatTag = WAVE_FORMAT_PCM; |
632 | |
633 /* Determine the audio parameters from the AudioSpec */ | |
634 switch ( spec->format & 0xFF ) { | |
635 case 8: | |
636 /* Unsigned 8 bit audio data */ | |
637 spec->format = AUDIO_U8; | |
638 silence = 0x80; | |
639 waveformat.wBitsPerSample = 8; | |
640 break; | |
641 case 16: | |
642 /* Signed 16 bit audio data */ | |
643 spec->format = AUDIO_S16; | |
644 silence = 0x00; | |
645 waveformat.wBitsPerSample = 16; | |
646 break; | |
647 default: | |
648 SDL_SetError("Unsupported audio format"); | |
649 return(-1); | |
650 } | |
651 waveformat.nChannels = spec->channels; | |
652 waveformat.nSamplesPerSec = spec->freq; | |
653 waveformat.nBlockAlign = | |
654 waveformat.nChannels * (waveformat.wBitsPerSample/8); | |
655 waveformat.nAvgBytesPerSec = | |
656 waveformat.nSamplesPerSec * waveformat.nBlockAlign; | |
657 | |
658 /* Update the fragment size as size in bytes */ | |
659 SDL_CalculateAudioSpec(spec); | |
660 | |
661 /* Open the audio device */ | |
662 result = DSoundCreate(NULL, &sound, NULL); | |
663 if ( result != DS_OK ) { | |
664 SetDSerror("DirectSoundCreate", result); | |
665 return(-1); | |
666 } | |
667 | |
668 /* Create the audio buffer to which we write */ | |
669 NUM_BUFFERS = -1; | |
375
17976f0f503f
Use secondary audio buffers to avoid problems on various soundcards
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
670 #ifdef USE_PRIMARY_BUFFER |
0 | 671 if ( mainwin ) { |
672 NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf, | |
673 &waveformat, spec->size); | |
674 } | |
375
17976f0f503f
Use secondary audio buffers to avoid problems on various soundcards
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
675 #endif /* USE_PRIMARY_BUFFER */ |
0 | 676 if ( NUM_BUFFERS < 0 ) { |
677 NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf, | |
678 &waveformat, spec->size); | |
679 if ( NUM_BUFFERS < 0 ) { | |
680 return(-1); | |
681 } | |
682 #ifdef DEBUG_SOUND | |
683 fprintf(stderr, "Using secondary audio buffer\n"); | |
684 #endif | |
685 } | |
686 #ifdef DEBUG_SOUND | |
687 else | |
688 fprintf(stderr, "Using primary audio buffer\n"); | |
689 #endif | |
690 | |
691 /* The buffer will auto-start playing in DX5_WaitAudio() */ | |
1877 | 692 lastchunk = 0; |
0 | 693 mixlen = spec->size; |
694 | |
695 #ifdef USE_POSITION_NOTIFY | |
696 /* See if we can use DirectX 6 event notification */ | |
697 if ( CreateAudioEvent(this) == 0 ) { | |
698 this->WaitAudio = DX6_WaitAudio_EventWait; | |
699 } else { | |
700 this->WaitAudio = DX5_WaitAudio_BusyWait; | |
701 } | |
702 #endif | |
703 return(0); | |
704 } | |
705 |