21 #include "../../SDL_internal.h" 23 #if SDL_AUDIO_DRIVER_WINMM 27 #include "../../core/windows/SDL_windows.h" 33 #include "../SDL_audio_c.h" 37 #if defined(__MINGW32__) && defined(_MMSYSTEM_H) 39 typedef struct tagWAVEINCAPS2W
43 MMVERSION vDriverVersion;
44 WCHAR szPname[MAXPNAMELEN];
48 GUID ManufacturerGuid;
51 } WAVEINCAPS2W,*PWAVEINCAPS2W,*NPWAVEINCAPS2W,*LPWAVEINCAPS2W;
53 typedef struct tagWAVEOUTCAPS2W
57 MMVERSION vDriverVersion;
58 WCHAR szPname[MAXPNAMELEN];
63 GUID ManufacturerGuid;
66 } WAVEOUTCAPS2W,*PWAVEOUTCAPS2W,*NPWAVEOUTCAPS2W,*LPWAVEOUTCAPS2W;
70 #ifndef WAVE_FORMAT_IEEE_FLOAT 71 #define WAVE_FORMAT_IEEE_FLOAT 0x0003 74 #define DETECT_DEV_IMPL(iscap, typ, capstyp) \ 75 static void DetectWave##typ##Devs(void) { \ 76 const UINT iscapture = iscap ? 1 : 0; \ 77 const UINT devcount = wave##typ##GetNumDevs(); \ 80 for (i = 0; i < devcount; i++) { \ 81 if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \ 82 char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \ 84 SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \ 91 DETECT_DEV_IMPL(
SDL_FALSE, Out, WAVEOUTCAPS)
92 DETECT_DEV_IMPL(
SDL_TRUE, In, WAVEINCAPS)
95 WINMM_DetectDevices(
void)
102 CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
103 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
108 if (uMsg != WIM_DATA)
112 ReleaseSemaphore(this->hidden->audio_sem, 1,
NULL);
118 FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
119 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
124 if (uMsg != WOM_DONE)
128 ReleaseSemaphore(this->hidden->audio_sem, 1,
NULL);
132 SetMMerror(
char *
function, MMRESULT code)
135 char errbuf[MAXERRORLENGTH];
136 wchar_t werrbuf[MAXERRORLENGTH];
141 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
142 WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
149 WINMM_WaitDevice(
_THIS)
152 WaitForSingleObject(this->hidden->audio_sem, INFINITE);
156 WINMM_GetDeviceBuf(
_THIS)
158 return (
Uint8 *) (this->hidden->
159 wavebuf[this->hidden->next_buffer].lpData);
163 WINMM_PlayDevice(
_THIS)
166 waveOutWrite(this->hidden->hout,
167 &this->hidden->wavebuf[this->hidden->next_buffer],
168 sizeof(this->hidden->wavebuf[0]));
169 this->hidden->next_buffer = (this->hidden->next_buffer + 1) %
NUM_BUFFERS;
173 WINMM_CaptureFromDevice(
_THIS,
void *
buffer,
int buflen)
175 const int nextbuf = this->hidden->next_buffer;
181 WaitForSingleObject(this->hidden->audio_sem, INFINITE);
184 SDL_memcpy(buffer, this->hidden->wavebuf[nextbuf].lpData, this->spec.size);
187 result = waveInAddBuffer(this->hidden->hin,
188 &this->hidden->wavebuf[nextbuf],
189 sizeof (this->hidden->wavebuf[nextbuf]));
190 if (result != MMSYSERR_NOERROR) {
195 this->hidden->next_buffer = (nextbuf + 1) %
NUM_BUFFERS;
200 WINMM_FlushCapture(
_THIS)
203 if (WaitForSingleObject(this->hidden->audio_sem, 0) == WAIT_OBJECT_0) {
204 const int nextbuf = this->hidden->next_buffer;
206 waveInAddBuffer(this->hidden->hin,
207 &this->hidden->wavebuf[nextbuf],
208 sizeof (this->hidden->wavebuf[nextbuf]));
209 this->hidden->next_buffer = (nextbuf + 1) %
NUM_BUFFERS;
214 WINMM_CloseDevice(
_THIS)
218 if (this->hidden->hout) {
219 waveOutReset(this->hidden->hout);
223 if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
224 waveOutUnprepareHeader(this->hidden->hout,
225 &this->hidden->wavebuf[i],
226 sizeof (this->hidden->wavebuf[i]));
230 waveOutClose(this->hidden->hout);
233 if (this->hidden->hin) {
234 waveInReset(this->hidden->hin);
238 if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
239 waveInUnprepareHeader(this->hidden->hin,
240 &this->hidden->wavebuf[i],
241 sizeof (this->hidden->wavebuf[i]));
244 waveInClose(this->hidden->hin);
247 if (this->hidden->audio_sem) {
248 CloseHandle(this->hidden->audio_sem);
256 PrepWaveFormat(
_THIS, UINT devId, WAVEFORMATEX *pfmt,
const int iscapture)
261 pfmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
263 pfmt->wFormatTag = WAVE_FORMAT_PCM;
268 pfmt->nSamplesPerSec = this->
spec.
freq;
269 pfmt->nBlockAlign = pfmt->nChannels * (pfmt->wBitsPerSample / 8);
270 pfmt->nAvgBytesPerSec = pfmt->nSamplesPerSec * pfmt->nBlockAlign;
273 return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
275 return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
280 WINMM_OpenDevice(
_THIS,
void *
handle,
const char *devname,
int iscapture)
283 int valid_datatype = 0;
285 WAVEFORMATEX waveformat;
286 UINT devId = WAVE_MAPPER;
289 if (handle !=
NULL) {
291 const size_t val = ((
size_t) handle) - 1;
298 if (this->hidden ==
NULL) {
305 this->hidden->wavebuf[i].dwUser = 0xFFFF;
310 while ((!valid_datatype) && (test_format)) {
311 switch (test_format) {
317 if (PrepWaveFormat(
this, devId, &waveformat, iscapture)) {
330 if (!valid_datatype) {
339 result = waveInOpen(&this->hidden->hin, devId, &waveformat,
340 (DWORD_PTR) CaptureSound, (DWORD_PTR)
this,
342 if (result != MMSYSERR_NOERROR) {
343 return SetMMerror(
"waveInOpen()", result);
346 result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
347 (DWORD_PTR) FillSound, (DWORD_PTR)
this,
349 if (result != MMSYSERR_NOERROR) {
350 return SetMMerror(
"waveOutOpen()", result);
359 result = waveInGetDevCaps((UINT) this->hidden->hout,
360 &caps, sizeof (caps));
361 if (result != MMSYSERR_NOERROR) {
362 return SetMMerror(
"waveInGetDevCaps()", result);
364 printf(
"Audio device: %s\n", caps.szPname);
367 result = waveOutGetDevCaps((UINT) this->hidden->hout,
368 &caps,
sizeof(caps));
369 if (result != MMSYSERR_NOERROR) {
370 return SetMMerror(
"waveOutGetDevCaps()", result);
372 printf(
"Audio device: %s\n", caps.szPname);
378 this->hidden->audio_sem =
379 CreateSemaphore(
NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS,
NULL);
380 if (this->hidden->audio_sem ==
NULL) {
385 this->hidden->mixbuf =
387 if (this->hidden->mixbuf ==
NULL) {
393 this->hidden->wavebuf[
i].dwBufferLength = this->
spec.
size;
394 this->hidden->wavebuf[
i].dwFlags = WHDR_DONE;
395 this->hidden->wavebuf[
i].lpData =
396 (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
399 result = waveInPrepareHeader(this->hidden->hin,
400 &this->hidden->wavebuf[i],
401 sizeof(this->hidden->wavebuf[i]));
402 if (result != MMSYSERR_NOERROR) {
403 return SetMMerror(
"waveInPrepareHeader()", result);
406 result = waveInAddBuffer(this->hidden->hin,
407 &this->hidden->wavebuf[i],
408 sizeof(this->hidden->wavebuf[i]));
409 if (result != MMSYSERR_NOERROR) {
410 return SetMMerror(
"waveInAddBuffer()", result);
413 result = waveOutPrepareHeader(this->hidden->hout,
414 &this->hidden->wavebuf[i],
415 sizeof(this->hidden->wavebuf[i]));
416 if (result != MMSYSERR_NOERROR) {
417 return SetMMerror(
"waveOutPrepareHeader()", result);
423 result = waveInStart(this->hidden->hin);
424 if (result != MMSYSERR_NOERROR) {
425 return SetMMerror(
"waveInStart()", result);
452 "winmm",
"Windows Waveform Audio", WINMM_Init, 0
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
void(* DetectDevices)(void)
void(* PlayDevice)(_THIS)
void(* WaitDevice)(_THIS)
Uint16 SDL_AudioFormat
Audio format flags.
SDL_AudioFormat SDL_NextAudioFormat(void)
#define SDL_AUDIO_ISFLOAT(x)
EGLImageKHR EGLint EGLint * handle
#define SDL_AUDIO_BITSIZE(x)
#define SDL_static_cast(type, expression)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
AudioBootStrap WINMM_bootstrap
#define SDL_assert(condition)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
#define SDL_OutOfMemory()
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
void(* CloseDevice)(_THIS)
void(* FlushCapture)(_THIS)
Uint8 *(* GetDeviceBuf)(_THIS)
#define SDL_arraysize(array)