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);
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;
298 if (this->hidden ==
NULL) {
305 this->hidden->wavebuf[
i].dwUser = 0xFFFF;
310 while ((!valid_datatype) && (test_format)) {
311 switch (test_format) {
330 if (!valid_datatype) {
340 (DWORD_PTR) CaptureSound, (DWORD_PTR)
this,
342 if (
result != MMSYSERR_NOERROR) {
343 return SetMMerror(
"waveInOpen()",
result);
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);
379 if (this->hidden->audio_sem ==
NULL) {
384 this->hidden->mixbuf =
386 if (this->hidden->mixbuf ==
NULL) {
392 this->hidden->wavebuf[
i].dwBufferLength = this->
spec.
size;
393 this->hidden->wavebuf[
i].dwFlags = WHDR_DONE;
394 this->hidden->wavebuf[
i].lpData =
395 (LPSTR) & this->hidden->mixbuf[
i * this->spec.size];
398 result = waveInPrepareHeader(this->hidden->hin,
399 &this->hidden->wavebuf[
i],
400 sizeof(this->hidden->wavebuf[
i]));
401 if (
result != MMSYSERR_NOERROR) {
402 return SetMMerror(
"waveInPrepareHeader()",
result);
405 result = waveInAddBuffer(this->hidden->hin,
406 &this->hidden->wavebuf[
i],
407 sizeof(this->hidden->wavebuf[
i]));
408 if (
result != MMSYSERR_NOERROR) {
409 return SetMMerror(
"waveInAddBuffer()",
result);
412 result = waveOutPrepareHeader(this->hidden->hout,
413 &this->hidden->wavebuf[
i],
414 sizeof(this->hidden->wavebuf[
i]));
415 if (
result != MMSYSERR_NOERROR) {
416 return SetMMerror(
"waveOutPrepareHeader()",
result);
422 result = waveInStart(this->hidden->hin);
423 if (
result != MMSYSERR_NOERROR) {
424 return SetMMerror(
"waveInStart()",
result);
451 "winmm",
"Windows Waveform Audio", WINMM_Init, 0