Mercurial > sdl-ios-xcode
annotate src/audio/windib/SDL_dibaudio.c @ 4541:abb56f7699ea SDL-1.2
Fixed bug 936
Make sure that eip doesn't overflow the copy buffer beforehand. :)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 18 Jul 2010 10:08:06 -0700 |
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:
36
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 | |
1433
bb6839704ed6
SDL_windows.h is no longer necessary
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
26 #define WIN32_LEAN_AND_MEAN |
bb6839704ed6
SDL_windows.h is no longer necessary
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
27 #include <windows.h> |
0 | 28 #include <mmsystem.h> |
29 | |
1358
c71e05b4dc2e
More header massaging... works great on Windows. ;-)
Sam Lantinga <slouken@libsdl.org>
parents:
1338
diff
changeset
|
30 #include "SDL_timer.h" |
0 | 31 #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
|
32 #include "../SDL_audio_c.h" |
0 | 33 #include "SDL_dibaudio.h" |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
34 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
35 #include "win_ce_semaphore.h" |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
36 #endif |
0 | 37 |
38 | |
39 /* Audio driver functions */ | |
40 static int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
41 static void DIB_ThreadInit(_THIS); | |
42 static void DIB_WaitAudio(_THIS); | |
43 static Uint8 *DIB_GetAudioBuf(_THIS); | |
44 static void DIB_PlayAudio(_THIS); | |
45 static void DIB_WaitDone(_THIS); | |
46 static void DIB_CloseAudio(_THIS); | |
47 | |
48 /* Audio driver bootstrap functions */ | |
49 | |
50 static int Audio_Available(void) | |
51 { | |
52 return(1); | |
53 } | |
54 | |
55 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
56 { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
57 SDL_free(device->hidden); |
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
58 SDL_free(device); |
0 | 59 } |
60 | |
61 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
62 { | |
63 SDL_AudioDevice *this; | |
64 | |
65 /* 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
|
66 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); |
0 | 67 if ( this ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
68 SDL_memset(this, 0, (sizeof *this)); |
0 | 69 this->hidden = (struct SDL_PrivateAudioData *) |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
70 SDL_malloc((sizeof *this->hidden)); |
0 | 71 } |
72 if ( (this == NULL) || (this->hidden == NULL) ) { | |
73 SDL_OutOfMemory(); | |
74 if ( this ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
75 SDL_free(this); |
0 | 76 } |
77 return(0); | |
78 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
79 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
0 | 80 |
81 /* Set the function pointers */ | |
82 this->OpenAudio = DIB_OpenAudio; | |
83 this->ThreadInit = DIB_ThreadInit; | |
84 this->WaitAudio = DIB_WaitAudio; | |
85 this->PlayAudio = DIB_PlayAudio; | |
86 this->GetAudioBuf = DIB_GetAudioBuf; | |
87 this->WaitDone = DIB_WaitDone; | |
88 this->CloseAudio = DIB_CloseAudio; | |
89 | |
90 this->free = Audio_DeleteDevice; | |
91 | |
92 return this; | |
93 } | |
94 | |
95 AudioBootStrap WAVEOUT_bootstrap = { | |
96 "waveout", "Win95/98/NT/2000 WaveOut", | |
97 Audio_Available, Audio_CreateDevice | |
98 }; | |
99 | |
100 | |
101 /* The Win32 callback for filling the WAVE device */ | |
1456
84de7511f79f
Fixed a bunch of 64-bit compatibility problems
Sam Lantinga <slouken@libsdl.org>
parents:
1433
diff
changeset
|
102 static void CALLBACK FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, |
0 | 103 DWORD dwParam1, DWORD dwParam2) |
104 { | |
105 SDL_AudioDevice *this = (SDL_AudioDevice *)dwInstance; | |
106 | |
107 /* Only service "buffer done playing" messages */ | |
108 if ( uMsg != WOM_DONE ) | |
109 return; | |
110 | |
111 /* Signal that we are done playing a buffer */ | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
112 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
113 ReleaseSemaphoreCE(audio_sem, 1, NULL); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
114 #else |
0 | 115 ReleaseSemaphore(audio_sem, 1, NULL); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
116 #endif |
0 | 117 } |
118 | |
119 static void SetMMerror(char *function, MMRESULT code) | |
120 { | |
1456
84de7511f79f
Fixed a bunch of 64-bit compatibility problems
Sam Lantinga <slouken@libsdl.org>
parents:
1433
diff
changeset
|
121 size_t len; |
0 | 122 char errbuf[MAXERRORLENGTH]; |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
123 #ifdef _WIN32_WCE |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
124 wchar_t werrbuf[MAXERRORLENGTH]; |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
125 #endif |
0 | 126 |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
127 SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function); |
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
128 len = SDL_strlen(errbuf); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
129 |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
130 #ifdef _WIN32_WCE |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
131 /* UNICODE version */ |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
132 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH-len); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
133 WideCharToMultiByte(CP_ACP,0,werrbuf,-1,errbuf+len,MAXERRORLENGTH-len,NULL,NULL); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
134 #else |
1456
84de7511f79f
Fixed a bunch of 64-bit compatibility problems
Sam Lantinga <slouken@libsdl.org>
parents:
1433
diff
changeset
|
135 waveOutGetErrorText(code, errbuf+len, (UINT)(MAXERRORLENGTH-len)); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
136 #endif |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
137 |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
138 SDL_SetError("%s",errbuf); |
0 | 139 } |
140 | |
141 /* Set high priority for the audio thread */ | |
142 static void DIB_ThreadInit(_THIS) | |
143 { | |
144 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); | |
145 } | |
146 | |
147 void DIB_WaitAudio(_THIS) | |
148 { | |
149 /* Wait for an audio chunk to finish */ | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
150 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
151 WaitForSemaphoreCE(audio_sem, INFINITE); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
152 #else |
0 | 153 WaitForSingleObject(audio_sem, INFINITE); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
154 #endif |
0 | 155 } |
156 | |
157 Uint8 *DIB_GetAudioBuf(_THIS) | |
158 { | |
159 Uint8 *retval; | |
160 | |
161 retval = (Uint8 *)(wavebuf[next_buffer].lpData); | |
162 return retval; | |
163 } | |
164 | |
165 void DIB_PlayAudio(_THIS) | |
166 { | |
167 /* Queue it up */ | |
168 waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0])); | |
169 next_buffer = (next_buffer+1)%NUM_BUFFERS; | |
170 } | |
171 | |
172 void DIB_WaitDone(_THIS) | |
173 { | |
174 int i, left; | |
175 | |
176 do { | |
177 left = NUM_BUFFERS; | |
178 for ( i=0; i<NUM_BUFFERS; ++i ) { | |
179 if ( wavebuf[i].dwFlags & WHDR_DONE ) { | |
180 --left; | |
181 } | |
182 } | |
183 if ( left > 0 ) { | |
184 SDL_Delay(100); | |
185 } | |
186 } while ( left > 0 ); | |
187 } | |
188 | |
189 void DIB_CloseAudio(_THIS) | |
190 { | |
191 int i; | |
192 | |
193 /* Close up audio */ | |
194 if ( audio_sem ) { | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
195 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
196 CloseSynchHandle(audio_sem); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
197 #else |
0 | 198 CloseHandle(audio_sem); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
199 #endif |
0 | 200 } |
201 if ( sound ) { | |
202 waveOutClose(sound); | |
203 } | |
204 | |
205 /* Clean up mixing buffers */ | |
206 for ( i=0; i<NUM_BUFFERS; ++i ) { | |
207 if ( wavebuf[i].dwUser != 0xFFFF ) { | |
208 waveOutUnprepareHeader(sound, &wavebuf[i], | |
209 sizeof(wavebuf[i])); | |
210 wavebuf[i].dwUser = 0xFFFF; | |
211 } | |
212 } | |
213 /* Free raw mixing buffer */ | |
214 if ( mixbuf != NULL ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
215 SDL_free(mixbuf); |
0 | 216 mixbuf = NULL; |
217 } | |
218 } | |
219 | |
220 int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
221 { | |
222 MMRESULT result; | |
223 int i; | |
224 WAVEFORMATEX waveformat; | |
225 | |
226 /* Initialize the wavebuf structures for closing */ | |
227 sound = NULL; | |
228 audio_sem = NULL; | |
229 for ( i = 0; i < NUM_BUFFERS; ++i ) | |
230 wavebuf[i].dwUser = 0xFFFF; | |
231 mixbuf = NULL; | |
232 | |
233 /* Set basic WAVE format parameters */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
234 SDL_memset(&waveformat, 0, sizeof(waveformat)); |
0 | 235 waveformat.wFormatTag = WAVE_FORMAT_PCM; |
236 | |
237 /* Determine the audio parameters from the AudioSpec */ | |
238 switch ( spec->format & 0xFF ) { | |
239 case 8: | |
240 /* Unsigned 8 bit audio data */ | |
241 spec->format = AUDIO_U8; | |
242 waveformat.wBitsPerSample = 8; | |
243 break; | |
244 case 16: | |
245 /* Signed 16 bit audio data */ | |
246 spec->format = AUDIO_S16; | |
247 waveformat.wBitsPerSample = 16; | |
248 break; | |
249 default: | |
250 SDL_SetError("Unsupported audio format"); | |
251 return(-1); | |
252 } | |
253 waveformat.nChannels = spec->channels; | |
254 waveformat.nSamplesPerSec = spec->freq; | |
255 waveformat.nBlockAlign = | |
256 waveformat.nChannels * (waveformat.wBitsPerSample/8); | |
257 waveformat.nAvgBytesPerSec = | |
258 waveformat.nSamplesPerSec * waveformat.nBlockAlign; | |
259 | |
260 /* Check the buffer size -- minimum of 1/4 second (word aligned) */ | |
261 if ( spec->samples < (spec->freq/4) ) | |
262 spec->samples = ((spec->freq/4)+3)&~3; | |
263 | |
264 /* Update the fragment size as size in bytes */ | |
265 SDL_CalculateAudioSpec(spec); | |
266 | |
267 /* Open the audio device */ | |
268 result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat, | |
1456
84de7511f79f
Fixed a bunch of 64-bit compatibility problems
Sam Lantinga <slouken@libsdl.org>
parents:
1433
diff
changeset
|
269 (DWORD_PTR)FillSound, (DWORD_PTR)this, CALLBACK_FUNCTION); |
0 | 270 if ( result != MMSYSERR_NOERROR ) { |
271 SetMMerror("waveOutOpen()", result); | |
272 return(-1); | |
273 } | |
274 | |
275 #ifdef SOUND_DEBUG | |
276 /* Check the sound device we retrieved */ | |
277 { | |
278 WAVEOUTCAPS caps; | |
279 | |
280 result = waveOutGetDevCaps((UINT)sound, &caps, sizeof(caps)); | |
281 if ( result != MMSYSERR_NOERROR ) { | |
282 SetMMerror("waveOutGetDevCaps()", result); | |
283 return(-1); | |
284 } | |
285 printf("Audio device: %s\n", caps.szPname); | |
286 } | |
287 #endif | |
288 | |
289 /* Create the audio buffer semaphore */ | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
290 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
291 audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS-1, NUM_BUFFERS, NULL); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
292 #else |
0 | 293 audio_sem = CreateSemaphore(NULL, NUM_BUFFERS-1, NUM_BUFFERS, NULL); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
294 #endif |
0 | 295 if ( audio_sem == NULL ) { |
296 SDL_SetError("Couldn't create semaphore"); | |
297 return(-1); | |
298 } | |
299 | |
300 /* Create the sound buffers */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
301 mixbuf = (Uint8 *)SDL_malloc(NUM_BUFFERS*spec->size); |
0 | 302 if ( mixbuf == NULL ) { |
303 SDL_SetError("Out of memory"); | |
304 return(-1); | |
305 } | |
306 for ( i = 0; i < NUM_BUFFERS; ++i ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
307 SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i])); |
0 | 308 wavebuf[i].lpData = (LPSTR) &mixbuf[i*spec->size]; |
309 wavebuf[i].dwBufferLength = spec->size; | |
310 wavebuf[i].dwFlags = WHDR_DONE; | |
311 result = waveOutPrepareHeader(sound, &wavebuf[i], | |
312 sizeof(wavebuf[i])); | |
313 if ( result != MMSYSERR_NOERROR ) { | |
314 SetMMerror("waveOutPrepareHeader()", result); | |
315 return(-1); | |
316 } | |
317 } | |
318 | |
319 /* Ready to go! */ | |
320 next_buffer = 0; | |
321 return(0); | |
322 } |