Mercurial > sdl-ios-xcode
annotate src/audio/windib/SDL_dibaudio.c @ 1295:c3e36ac8a94c
Date: Sun, 6 Mar 2005 17:06:20 +0100
From: Per Inge Mathisen
Subject: [SDL] Fullscreen refresh on win32
Windows has a terrible default for fullscreen 3D apps of 60mhz refresh
rate. This can be fixed by the user by going into his driver's
control panel and forcing the refresh rate higher. However, this not a
very user friendly way about it, and in any case SDL contains no code
that could figure out this that condition has afflicted the user.
So the question is, could SDL fix this for the user? It is possible
under Windows to request a higher refresh rate. The danger is of
course that if the user has an old monitor, and you request a too high
refresh rate, the monitor could be damaged. However, I believe there
might be a way around that: Check before switching what refresh rate
the user's desktop runs in, and if our fullscreen dimensions are equal
or less than those of the desktop, use the higher refresh rate of 60
and the desktop rate.
Since most users run their desktops in the same or higher resolution
something sane, this should fix this problem for most users.
Thoughts?
An alternative is to add an SDL_GL_GetAttribute(SDL_GL_REFRESH_RATE)
option so that programs can bitch at their users at their own
convenience.
- Per
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 30 Jan 2006 06:56:10 +0000 |
parents | b8d311d90021 |
children | c9b51268668f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
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 | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
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 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Allow access to a raw mixing buffer */ | |
29 | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <windows.h> | |
33 #include <mmsystem.h> | |
34 | |
35 #include "SDL_audio.h" | |
36 #include "SDL_mutex.h" | |
37 #include "SDL_timer.h" | |
38 #include "SDL_audio_c.h" | |
39 #include "SDL_dibaudio.h" | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
40 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
41 #include "win_ce_semaphore.h" |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
42 #endif |
0 | 43 |
44 | |
45 /* Audio driver functions */ | |
46 static int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
47 static void DIB_ThreadInit(_THIS); | |
48 static void DIB_WaitAudio(_THIS); | |
49 static Uint8 *DIB_GetAudioBuf(_THIS); | |
50 static void DIB_PlayAudio(_THIS); | |
51 static void DIB_WaitDone(_THIS); | |
52 static void DIB_CloseAudio(_THIS); | |
53 | |
54 /* Audio driver bootstrap functions */ | |
55 | |
56 static int Audio_Available(void) | |
57 { | |
58 return(1); | |
59 } | |
60 | |
61 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
62 { | |
63 free(device->hidden); | |
64 free(device); | |
65 } | |
66 | |
67 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
68 { | |
69 SDL_AudioDevice *this; | |
70 | |
71 /* Initialize all variables that we clean on shutdown */ | |
72 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); | |
73 if ( this ) { | |
74 memset(this, 0, (sizeof *this)); | |
75 this->hidden = (struct SDL_PrivateAudioData *) | |
76 malloc((sizeof *this->hidden)); | |
77 } | |
78 if ( (this == NULL) || (this->hidden == NULL) ) { | |
79 SDL_OutOfMemory(); | |
80 if ( this ) { | |
81 free(this); | |
82 } | |
83 return(0); | |
84 } | |
85 memset(this->hidden, 0, (sizeof *this->hidden)); | |
86 | |
87 /* Set the function pointers */ | |
88 this->OpenAudio = DIB_OpenAudio; | |
89 this->ThreadInit = DIB_ThreadInit; | |
90 this->WaitAudio = DIB_WaitAudio; | |
91 this->PlayAudio = DIB_PlayAudio; | |
92 this->GetAudioBuf = DIB_GetAudioBuf; | |
93 this->WaitDone = DIB_WaitDone; | |
94 this->CloseAudio = DIB_CloseAudio; | |
95 | |
96 this->free = Audio_DeleteDevice; | |
97 | |
98 return this; | |
99 } | |
100 | |
101 AudioBootStrap WAVEOUT_bootstrap = { | |
102 "waveout", "Win95/98/NT/2000 WaveOut", | |
103 Audio_Available, Audio_CreateDevice | |
104 }; | |
105 | |
106 | |
107 /* The Win32 callback for filling the WAVE device */ | |
108 static void CALLBACK FillSound(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, | |
109 DWORD dwParam1, DWORD dwParam2) | |
110 { | |
111 SDL_AudioDevice *this = (SDL_AudioDevice *)dwInstance; | |
112 | |
113 /* Only service "buffer done playing" messages */ | |
114 if ( uMsg != WOM_DONE ) | |
115 return; | |
116 | |
117 /* 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
|
118 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
119 ReleaseSemaphoreCE(audio_sem, 1, NULL); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
120 #else |
0 | 121 ReleaseSemaphore(audio_sem, 1, NULL); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
122 #endif |
0 | 123 } |
124 | |
125 static void SetMMerror(char *function, MMRESULT code) | |
126 { | |
127 int len; | |
128 char errbuf[MAXERRORLENGTH]; | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
129 #ifdef _WIN32_WCE |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
130 wchar_t werrbuf[MAXERRORLENGTH]; |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
131 #endif |
0 | 132 |
133 sprintf(errbuf, "%s: ", function); | |
134 len = strlen(errbuf); | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
135 |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
136 #ifdef _WIN32_WCE |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
137 /* UNICODE version */ |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
138 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH-len); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
139 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
|
140 #else |
0 | 141 waveOutGetErrorText(code, errbuf+len, MAXERRORLENGTH-len); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
142 #endif |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
143 |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
144 SDL_SetError("%s",errbuf); |
0 | 145 } |
146 | |
147 /* Set high priority for the audio thread */ | |
148 static void DIB_ThreadInit(_THIS) | |
149 { | |
150 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); | |
151 } | |
152 | |
153 void DIB_WaitAudio(_THIS) | |
154 { | |
155 /* 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
|
156 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
157 WaitForSemaphoreCE(audio_sem, INFINITE); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
158 #else |
0 | 159 WaitForSingleObject(audio_sem, INFINITE); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
160 #endif |
0 | 161 } |
162 | |
163 Uint8 *DIB_GetAudioBuf(_THIS) | |
164 { | |
165 Uint8 *retval; | |
166 | |
167 retval = (Uint8 *)(wavebuf[next_buffer].lpData); | |
168 return retval; | |
169 } | |
170 | |
171 void DIB_PlayAudio(_THIS) | |
172 { | |
173 /* Queue it up */ | |
174 waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0])); | |
175 next_buffer = (next_buffer+1)%NUM_BUFFERS; | |
176 } | |
177 | |
178 void DIB_WaitDone(_THIS) | |
179 { | |
180 int i, left; | |
181 | |
182 do { | |
183 left = NUM_BUFFERS; | |
184 for ( i=0; i<NUM_BUFFERS; ++i ) { | |
185 if ( wavebuf[i].dwFlags & WHDR_DONE ) { | |
186 --left; | |
187 } | |
188 } | |
189 if ( left > 0 ) { | |
190 SDL_Delay(100); | |
191 } | |
192 } while ( left > 0 ); | |
193 } | |
194 | |
195 void DIB_CloseAudio(_THIS) | |
196 { | |
197 int i; | |
198 | |
199 /* Close up audio */ | |
200 if ( audio_sem ) { | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
201 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
202 CloseSynchHandle(audio_sem); |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
203 #else |
0 | 204 CloseHandle(audio_sem); |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
205 #endif |
0 | 206 } |
207 if ( sound ) { | |
208 waveOutClose(sound); | |
209 } | |
210 | |
211 /* Clean up mixing buffers */ | |
212 for ( i=0; i<NUM_BUFFERS; ++i ) { | |
213 if ( wavebuf[i].dwUser != 0xFFFF ) { | |
214 waveOutUnprepareHeader(sound, &wavebuf[i], | |
215 sizeof(wavebuf[i])); | |
216 wavebuf[i].dwUser = 0xFFFF; | |
217 } | |
218 } | |
219 /* Free raw mixing buffer */ | |
220 if ( mixbuf != NULL ) { | |
221 free(mixbuf); | |
222 mixbuf = NULL; | |
223 } | |
224 } | |
225 | |
226 int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
227 { | |
228 MMRESULT result; | |
229 int i; | |
230 WAVEFORMATEX waveformat; | |
231 | |
232 /* Initialize the wavebuf structures for closing */ | |
233 sound = NULL; | |
234 audio_sem = NULL; | |
235 for ( i = 0; i < NUM_BUFFERS; ++i ) | |
236 wavebuf[i].dwUser = 0xFFFF; | |
237 mixbuf = NULL; | |
238 | |
239 /* Set basic WAVE format parameters */ | |
240 memset(&waveformat, 0, sizeof(waveformat)); | |
241 waveformat.wFormatTag = WAVE_FORMAT_PCM; | |
242 | |
243 /* Determine the audio parameters from the AudioSpec */ | |
244 switch ( spec->format & 0xFF ) { | |
245 case 8: | |
246 /* Unsigned 8 bit audio data */ | |
247 spec->format = AUDIO_U8; | |
248 waveformat.wBitsPerSample = 8; | |
249 break; | |
250 case 16: | |
251 /* Signed 16 bit audio data */ | |
252 spec->format = AUDIO_S16; | |
253 waveformat.wBitsPerSample = 16; | |
254 break; | |
255 default: | |
256 SDL_SetError("Unsupported audio format"); | |
257 return(-1); | |
258 } | |
259 waveformat.nChannels = spec->channels; | |
260 waveformat.nSamplesPerSec = spec->freq; | |
261 waveformat.nBlockAlign = | |
262 waveformat.nChannels * (waveformat.wBitsPerSample/8); | |
263 waveformat.nAvgBytesPerSec = | |
264 waveformat.nSamplesPerSec * waveformat.nBlockAlign; | |
265 | |
266 /* Check the buffer size -- minimum of 1/4 second (word aligned) */ | |
267 if ( spec->samples < (spec->freq/4) ) | |
268 spec->samples = ((spec->freq/4)+3)&~3; | |
269 | |
270 /* Update the fragment size as size in bytes */ | |
271 SDL_CalculateAudioSpec(spec); | |
272 | |
273 /* Open the audio device */ | |
274 result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat, | |
275 (DWORD)FillSound, (DWORD)this, CALLBACK_FUNCTION); | |
276 if ( result != MMSYSERR_NOERROR ) { | |
277 SetMMerror("waveOutOpen()", result); | |
278 return(-1); | |
279 } | |
280 | |
281 #ifdef SOUND_DEBUG | |
282 /* Check the sound device we retrieved */ | |
283 { | |
284 WAVEOUTCAPS caps; | |
285 | |
286 result = waveOutGetDevCaps((UINT)sound, &caps, sizeof(caps)); | |
287 if ( result != MMSYSERR_NOERROR ) { | |
288 SetMMerror("waveOutGetDevCaps()", result); | |
289 return(-1); | |
290 } | |
291 printf("Audio device: %s\n", caps.szPname); | |
292 } | |
293 #endif | |
294 | |
295 /* Create the audio buffer semaphore */ | |
36
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
296 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) |
13ee9f4834ea
Windows CE patches contributed by Rainer Loritz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
297 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
|
298 #else |
0 | 299 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
|
300 #endif |
0 | 301 if ( audio_sem == NULL ) { |
302 SDL_SetError("Couldn't create semaphore"); | |
303 return(-1); | |
304 } | |
305 | |
306 /* Create the sound buffers */ | |
307 mixbuf = (Uint8 *)malloc(NUM_BUFFERS*spec->size); | |
308 if ( mixbuf == NULL ) { | |
309 SDL_SetError("Out of memory"); | |
310 return(-1); | |
311 } | |
312 for ( i = 0; i < NUM_BUFFERS; ++i ) { | |
313 memset(&wavebuf[i], 0, sizeof(wavebuf[i])); | |
314 wavebuf[i].lpData = (LPSTR) &mixbuf[i*spec->size]; | |
315 wavebuf[i].dwBufferLength = spec->size; | |
316 wavebuf[i].dwFlags = WHDR_DONE; | |
317 result = waveOutPrepareHeader(sound, &wavebuf[i], | |
318 sizeof(wavebuf[i])); | |
319 if ( result != MMSYSERR_NOERROR ) { | |
320 SetMMerror("waveOutPrepareHeader()", result); | |
321 return(-1); | |
322 } | |
323 } | |
324 | |
325 /* Ready to go! */ | |
326 next_buffer = 0; | |
327 return(0); | |
328 } |