Mercurial > sdl-ios-xcode
annotate src/audio/windx5/SDL_dx5audio.c @ 1614:6162b8d921ce
Date: Wed, 29 Mar 2006 17:26:55 +0200 CEST
From: "Fran���is Revol"
Subject: [SDL] BeOS port fix: PrintScreen key crashing
It seems the latest SDL crashes when someone hits the PrtScrn key in
ZETA (BeOS R6), somewhere it gets a negative value as key code (or a
big unsigned maybe ?), and uses it as an index in the keysym table...
I'll investigate the cause for the negative value, but it's always
better to check for bounds correctly when indexing a table. The
attached diff fixes it.
Fran���is Revol
--
Software Architect
yellowTAB GmbH
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 31 Mar 2006 06:16:20 +0000 |
parents | d910939febfa |
children | 782fd950bd46 9b02a5b97f79 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
3 Copyright (C) 1997-2006 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 */ | |
257 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk); | |
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 cursor /= mixlen; | |
268 | |
269 while ( cursor == playing ) { | |
270 /* FIXME: find out how much time is left and sleep that long */ | |
271 SDL_Delay(10); | |
272 | |
273 /* Try to restore a lost sound buffer */ | |
274 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
275 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
276 IDirectSoundBuffer_Restore(mixbuf); | |
277 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
278 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
279 break; | |
280 } | |
281 } | |
282 if ( ! (status&DSBSTATUS_PLAYING) ) { | |
283 result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); | |
284 if ( result == DS_OK ) { | |
285 continue; | |
286 } | |
287 #ifdef DEBUG_SOUND | |
288 SetDSerror("DirectSound Play", result); | |
289 #endif | |
290 return; | |
291 } | |
292 | |
293 /* Find out where we are playing */ | |
294 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, | |
295 &cursor, &junk); | |
296 if ( result != DS_OK ) { | |
297 SetDSerror("DirectSound GetCurrentPosition", result); | |
298 return; | |
299 } | |
300 cursor /= mixlen; | |
301 } | |
302 } | |
303 | |
304 #ifdef USE_POSITION_NOTIFY | |
305 static void DX6_WaitAudio_EventWait(_THIS) | |
306 { | |
307 DWORD status; | |
308 HRESULT result; | |
309 | |
310 /* Try to restore a lost sound buffer */ | |
311 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
312 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
313 IDirectSoundBuffer_Restore(mixbuf); | |
314 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
315 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
316 return; | |
317 } | |
318 } | |
319 if ( ! (status&DSBSTATUS_PLAYING) ) { | |
320 result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); | |
321 if ( result != DS_OK ) { | |
322 #ifdef DEBUG_SOUND | |
323 SetDSerror("DirectSound Play", result); | |
324 #endif | |
325 return; | |
326 } | |
327 } | |
328 WaitForSingleObject(audio_event, INFINITE); | |
329 } | |
330 #endif /* USE_POSITION_NOTIFY */ | |
331 | |
332 static void DX5_PlayAudio(_THIS) | |
333 { | |
334 /* Unlock the buffer, allowing it to play */ | |
335 if ( locked_buf ) { | |
336 IDirectSoundBuffer_Unlock(mixbuf, locked_buf, mixlen, NULL, 0); | |
337 } | |
338 | |
339 } | |
340 | |
341 static Uint8 *DX5_GetAudioBuf(_THIS) | |
342 { | |
343 DWORD cursor, junk; | |
344 HRESULT result; | |
345 DWORD rawlen; | |
346 | |
347 /* Figure out which blocks to fill next */ | |
348 locked_buf = NULL; | |
349 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk); | |
350 if ( result == DSERR_BUFFERLOST ) { | |
351 IDirectSoundBuffer_Restore(mixbuf); | |
352 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, | |
353 &cursor, &junk); | |
354 } | |
355 if ( result != DS_OK ) { | |
356 SetDSerror("DirectSound GetCurrentPosition", result); | |
357 return(NULL); | |
358 } | |
359 cursor /= mixlen; | |
360 playing = cursor; | |
361 cursor = (cursor+1)%NUM_BUFFERS; | |
362 cursor *= mixlen; | |
363 | |
364 /* Lock the audio buffer */ | |
365 result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, | |
366 (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); | |
367 if ( result == DSERR_BUFFERLOST ) { | |
368 IDirectSoundBuffer_Restore(mixbuf); | |
369 result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, | |
370 (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); | |
371 } | |
372 if ( result != DS_OK ) { | |
373 SetDSerror("DirectSound Lock", result); | |
374 return(NULL); | |
375 } | |
376 return(locked_buf); | |
377 } | |
378 | |
379 static void DX5_WaitDone(_THIS) | |
380 { | |
381 Uint8 *stream; | |
382 | |
383 /* Wait for the playing chunk to finish */ | |
384 stream = this->GetAudioBuf(this); | |
385 if ( stream != NULL ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
386 SDL_memset(stream, silence, mixlen); |
0 | 387 this->PlayAudio(this); |
388 } | |
389 this->WaitAudio(this); | |
390 | |
391 /* Stop the looping sound buffer */ | |
392 IDirectSoundBuffer_Stop(mixbuf); | |
393 } | |
394 | |
395 static void DX5_CloseAudio(_THIS) | |
396 { | |
397 if ( sound != NULL ) { | |
398 if ( mixbuf != NULL ) { | |
399 /* Clean up the audio buffer */ | |
400 IDirectSoundBuffer_Release(mixbuf); | |
401 mixbuf = NULL; | |
402 } | |
403 if ( audio_event != NULL ) { | |
404 CloseHandle(audio_event); | |
405 audio_event = NULL; | |
406 } | |
407 IDirectSound_Release(sound); | |
408 sound = NULL; | |
409 } | |
410 } | |
411 | |
469 | 412 #ifdef USE_PRIMARY_BUFFER |
0 | 413 /* This function tries to create a primary audio buffer, and returns the |
414 number of audio chunks available in the created buffer. | |
415 */ | |
416 static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, | |
417 LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) | |
418 { | |
419 HRESULT result; | |
420 DSBUFFERDESC format; | |
421 DSBCAPS caps; | |
422 int numchunks; | |
423 | |
424 /* Try to set primary mixing privileges */ | |
425 result = IDirectSound_SetCooperativeLevel(sndObj, focus, | |
426 DSSCL_WRITEPRIMARY); | |
427 if ( result != DS_OK ) { | |
428 #ifdef DEBUG_SOUND | |
429 SetDSerror("DirectSound SetCooperativeLevel", result); | |
430 #endif | |
431 return(-1); | |
432 } | |
433 | |
434 /* 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
|
435 SDL_memset(&format, 0, sizeof(format)); |
0 | 436 format.dwSize = sizeof(format); |
437 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
|
438 format.dwFlags |= DSBCAPS_STICKYFOCUS; |
0 | 439 #ifdef USE_POSITION_NOTIFY |
440 format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; | |
441 #endif | |
442 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); | |
443 if ( result != DS_OK ) { | |
444 #ifdef DEBUG_SOUND | |
445 SetDSerror("DirectSound CreateSoundBuffer", result); | |
446 #endif | |
447 return(-1); | |
448 } | |
449 | |
450 /* 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
|
451 SDL_memset(&caps, 0, sizeof(caps)); |
0 | 452 caps.dwSize = sizeof(caps); |
453 result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); | |
454 if ( result != DS_OK ) { | |
455 #ifdef DEBUG_SOUND | |
456 SetDSerror("DirectSound GetCaps", result); | |
457 #endif | |
458 IDirectSoundBuffer_Release(*sndbuf); | |
459 return(-1); | |
460 } | |
461 if ( (chunksize > caps.dwBufferBytes) || | |
462 ((caps.dwBufferBytes%chunksize) != 0) ) { | |
463 /* The primary buffer size is not a multiple of 'chunksize' | |
464 -- this hopefully doesn't happen when 'chunksize' is a | |
465 power of 2. | |
466 */ | |
467 IDirectSoundBuffer_Release(*sndbuf); | |
468 SDL_SetError( | |
469 "Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", | |
470 caps.dwBufferBytes, chunksize); | |
471 return(-1); | |
472 } | |
473 numchunks = (caps.dwBufferBytes/chunksize); | |
474 | |
475 /* Set the primary audio format */ | |
476 result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); | |
477 if ( result != DS_OK ) { | |
478 #ifdef DEBUG_SOUND | |
479 SetDSerror("DirectSound SetFormat", result); | |
480 #endif | |
481 IDirectSoundBuffer_Release(*sndbuf); | |
482 return(-1); | |
483 } | |
484 return(numchunks); | |
485 } | |
469 | 486 #endif /* USE_PRIMARY_BUFFER */ |
0 | 487 |
488 /* This function tries to create a secondary audio buffer, and returns the | |
489 number of audio chunks available in the created buffer. | |
490 */ | |
491 static int CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, | |
492 LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) | |
493 { | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
494 const int numchunks = 2; |
0 | 495 HRESULT result; |
496 DSBUFFERDESC format; | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
497 LPVOID pvAudioPtr1, pvAudioPtr2; |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
498 DWORD dwAudioBytes1, dwAudioBytes2; |
0 | 499 |
500 /* Try to set primary mixing privileges */ | |
501 if ( focus ) { | |
502 result = IDirectSound_SetCooperativeLevel(sndObj, | |
503 focus, DSSCL_PRIORITY); | |
504 } else { | |
505 result = IDirectSound_SetCooperativeLevel(sndObj, | |
506 GetDesktopWindow(), DSSCL_NORMAL); | |
507 } | |
508 if ( result != DS_OK ) { | |
509 #ifdef DEBUG_SOUND | |
510 SetDSerror("DirectSound SetCooperativeLevel", result); | |
511 #endif | |
512 return(-1); | |
513 } | |
514 | |
515 /* 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
|
516 SDL_memset(&format, 0, sizeof(format)); |
0 | 517 format.dwSize = sizeof(format); |
518 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2; | |
519 #ifdef USE_POSITION_NOTIFY | |
520 format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; | |
521 #endif | |
522 if ( ! focus ) { | |
523 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
|
524 } 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
|
525 format.dwFlags |= DSBCAPS_STICKYFOCUS; |
0 | 526 } |
527 format.dwBufferBytes = numchunks*chunksize; | |
528 if ( (format.dwBufferBytes < DSBSIZE_MIN) || | |
529 (format.dwBufferBytes > DSBSIZE_MAX) ) { | |
530 SDL_SetError("Sound buffer size must be between %d and %d", | |
531 DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks); | |
532 return(-1); | |
533 } | |
534 format.dwReserved = 0; | |
535 format.lpwfxFormat = wavefmt; | |
536 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); | |
537 if ( result != DS_OK ) { | |
538 SetDSerror("DirectSound CreateSoundBuffer", result); | |
539 return(-1); | |
540 } | |
541 IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); | |
542 | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
543 /* Silence the initial audio buffer */ |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
544 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
|
545 (LPVOID *)&pvAudioPtr1, &dwAudioBytes1, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
546 (LPVOID *)&pvAudioPtr2, &dwAudioBytes2, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
547 DSBLOCK_ENTIREBUFFER); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
548 if ( result == DS_OK ) { |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
549 if ( wavefmt->wBitsPerSample == 8 ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
550 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
|
551 } else { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
552 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
|
553 } |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
554 IDirectSoundBuffer_Unlock(*sndbuf, |
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 } |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
558 |
0 | 559 /* We're ready to go */ |
560 return(numchunks); | |
561 } | |
562 | |
563 /* This function tries to set position notify events on the mixing buffer */ | |
564 #ifdef USE_POSITION_NOTIFY | |
565 static int CreateAudioEvent(_THIS) | |
566 { | |
567 LPDIRECTSOUNDNOTIFY notify; | |
568 DSBPOSITIONNOTIFY *notify_positions; | |
569 int i, retval; | |
570 HRESULT result; | |
571 | |
572 /* Default to fail on exit */ | |
573 retval = -1; | |
574 notify = NULL; | |
575 | |
576 /* Query for the interface */ | |
577 result = IDirectSoundBuffer_QueryInterface(mixbuf, | |
578 &IID_IDirectSoundNotify, (void *)¬ify); | |
579 if ( result != DS_OK ) { | |
580 goto done; | |
581 } | |
582 | |
583 /* Allocate the notify structures */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
584 notify_positions = (DSBPOSITIONNOTIFY *)SDL_malloc(NUM_BUFFERS* |
0 | 585 sizeof(*notify_positions)); |
586 if ( notify_positions == NULL ) { | |
587 goto done; | |
588 } | |
589 | |
590 /* Create the notify event */ | |
591 audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); | |
592 if ( audio_event == NULL ) { | |
593 goto done; | |
594 } | |
595 | |
596 /* Set up the notify structures */ | |
597 for ( i=0; i<NUM_BUFFERS; ++i ) { | |
598 notify_positions[i].dwOffset = i*mixlen; | |
599 notify_positions[i].hEventNotify = audio_event; | |
600 } | |
601 result = IDirectSoundNotify_SetNotificationPositions(notify, | |
602 NUM_BUFFERS, notify_positions); | |
603 if ( result == DS_OK ) { | |
604 retval = 0; | |
605 } | |
606 done: | |
607 if ( notify != NULL ) { | |
608 IDirectSoundNotify_Release(notify); | |
609 } | |
610 return(retval); | |
611 } | |
612 #endif /* USE_POSITION_NOTIFY */ | |
613 | |
614 static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
615 { | |
616 HRESULT result; | |
617 WAVEFORMATEX waveformat; | |
618 | |
619 /* Set basic WAVE format parameters */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
620 SDL_memset(&waveformat, 0, sizeof(waveformat)); |
0 | 621 waveformat.wFormatTag = WAVE_FORMAT_PCM; |
622 | |
623 /* Determine the audio parameters from the AudioSpec */ | |
624 switch ( spec->format & 0xFF ) { | |
625 case 8: | |
626 /* Unsigned 8 bit audio data */ | |
627 spec->format = AUDIO_U8; | |
628 silence = 0x80; | |
629 waveformat.wBitsPerSample = 8; | |
630 break; | |
631 case 16: | |
632 /* Signed 16 bit audio data */ | |
633 spec->format = AUDIO_S16; | |
634 silence = 0x00; | |
635 waveformat.wBitsPerSample = 16; | |
636 break; | |
637 default: | |
638 SDL_SetError("Unsupported audio format"); | |
639 return(-1); | |
640 } | |
641 waveformat.nChannels = spec->channels; | |
642 waveformat.nSamplesPerSec = spec->freq; | |
643 waveformat.nBlockAlign = | |
644 waveformat.nChannels * (waveformat.wBitsPerSample/8); | |
645 waveformat.nAvgBytesPerSec = | |
646 waveformat.nSamplesPerSec * waveformat.nBlockAlign; | |
647 | |
648 /* Update the fragment size as size in bytes */ | |
649 SDL_CalculateAudioSpec(spec); | |
650 | |
651 /* Open the audio device */ | |
652 result = DSoundCreate(NULL, &sound, NULL); | |
653 if ( result != DS_OK ) { | |
654 SetDSerror("DirectSoundCreate", result); | |
655 return(-1); | |
656 } | |
657 | |
658 /* Create the audio buffer to which we write */ | |
659 NUM_BUFFERS = -1; | |
375
17976f0f503f
Use secondary audio buffers to avoid problems on various soundcards
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
660 #ifdef USE_PRIMARY_BUFFER |
0 | 661 if ( mainwin ) { |
662 NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf, | |
663 &waveformat, spec->size); | |
664 } | |
375
17976f0f503f
Use secondary audio buffers to avoid problems on various soundcards
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
665 #endif /* USE_PRIMARY_BUFFER */ |
0 | 666 if ( NUM_BUFFERS < 0 ) { |
667 NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf, | |
668 &waveformat, spec->size); | |
669 if ( NUM_BUFFERS < 0 ) { | |
670 return(-1); | |
671 } | |
672 #ifdef DEBUG_SOUND | |
673 fprintf(stderr, "Using secondary audio buffer\n"); | |
674 #endif | |
675 } | |
676 #ifdef DEBUG_SOUND | |
677 else | |
678 fprintf(stderr, "Using primary audio buffer\n"); | |
679 #endif | |
680 | |
681 /* The buffer will auto-start playing in DX5_WaitAudio() */ | |
682 playing = 0; | |
683 mixlen = spec->size; | |
684 | |
685 #ifdef USE_POSITION_NOTIFY | |
686 /* See if we can use DirectX 6 event notification */ | |
687 if ( CreateAudioEvent(this) == 0 ) { | |
688 this->WaitAudio = DX6_WaitAudio_EventWait; | |
689 } else { | |
690 this->WaitAudio = DX5_WaitAudio_BusyWait; | |
691 } | |
692 #endif | |
693 return(0); | |
694 } | |
695 |