Mercurial > sdl-ios-xcode
annotate src/audio/windib/SDL_dibaudio.c @ 641:df178851293b
Date: 28 Jun 2003 22:42:52 +0100
From: Alan Swanson
Subject: Re: [SDL] New XFree 4.3 Video Mode Patch
I have a wee amendment that moves the qsort in set_best_resolution
to only occur after failing to find an exact match only. This would
make absolutely sure we get a user set mode.
While I've never had any problems for my normal resolutions (1280x1024,
1024x768, 800x600 & 640,480) while closely examining the output from
qsort I've noticed it doesn't seem to sort the modes fully. These is
one definite wrong at 1152x768 and a few that just look wrong to me.
From a program (attached) I made to examine this more easily. X has
sorted its mode list using the same method as ours (plus frequency),
and our user modes get inserted without any other movement.
On the patch I've made I've also changed cmpmodes to sort on vertical
resolution and then horizontal. Ie vertical is now most significant
bit.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 28 Jun 2003 21:52:26 +0000 |
parents | f6ffac90895c |
children | b8d311d90021 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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 } |