23 #if SDL_AUDIO_DRIVER_WINMM
27 #include "../../core/windows/SDL_windows.h"
32 #include "../SDL_audio_c.h"
35 #ifndef WAVE_FORMAT_IEEE_FLOAT
36 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
39 #define DETECT_DEV_IMPL(typ, capstyp) \
40 static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
41 const UINT devcount = wave##typ##GetNumDevs(); \
44 for (i = 0; i < devcount; i++) { \
45 if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
46 char *name = WIN_StringToUTF8(caps.szPname); \
55 DETECT_DEV_IMPL(Out, WAVEOUTCAPS)
56 DETECT_DEV_IMPL(In, WAVEINCAPS)
62 DetectWaveInDevs(addfn);
64 DetectWaveOutDevs(addfn);
69 CaptureSound(HWAVEIN hwi,
UINT uMsg, DWORD_PTR dwInstance,
70 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
79 ReleaseSemaphore(this->hidden->audio_sem, 1,
NULL);
85 FillSound(HWAVEOUT hwo,
UINT uMsg, DWORD_PTR dwInstance,
86 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
95 ReleaseSemaphore(this->hidden->audio_sem, 1,
NULL);
99 SetMMerror(
char *
function, MMRESULT
code)
102 char errbuf[MAXERRORLENGTH];
103 wchar_t werrbuf[MAXERRORLENGTH];
108 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
109 WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
116 WINMM_WaitDevice(
_THIS)
119 WaitForSingleObject(this->hidden->audio_sem, INFINITE);
123 WINMM_GetDeviceBuf(
_THIS)
125 return (
Uint8 *) (this->hidden->
126 wavebuf[this->hidden->next_buffer].lpData);
130 WINMM_PlayDevice(
_THIS)
133 waveOutWrite(this->hidden->hout,
134 &this->hidden->wavebuf[this->hidden->next_buffer],
135 sizeof(this->hidden->wavebuf[0]));
136 this->hidden->next_buffer = (this->hidden->next_buffer + 1) %
NUM_BUFFERS;
140 WINMM_WaitDone(
_THIS)
147 if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
158 WINMM_CloseDevice(
_THIS)
161 if (this->hidden !=
NULL) {
164 if (this->hidden->audio_sem) {
165 CloseHandle(this->hidden->audio_sem);
166 this->hidden->audio_sem = 0;
171 if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
172 waveOutUnprepareHeader(this->hidden->hout,
173 &this->hidden->wavebuf[i],
174 sizeof(this->hidden->wavebuf[i]));
175 this->hidden->wavebuf[
i].dwUser = 0xFFFF;
181 this->hidden->mixbuf =
NULL;
183 if (this->hidden->hin) {
184 waveInClose(this->hidden->hin);
185 this->hidden->hin = 0;
188 if (this->hidden->hout) {
189 waveOutClose(this->hidden->hout);
190 this->hidden->hout = 0;
216 return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
218 return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
223 WINMM_OpenDevice(
_THIS,
const char *devname,
int iscapture)
226 int valid_datatype = 0;
229 UINT_PTR devId = WAVE_MAPPER;
233 if (devname !=
NULL) {
235 const int devcount = (
int) waveInGetNumDevs();
237 for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
238 result = waveInGetDevCaps(i, &caps,
sizeof (caps));
239 if (result != MMSYSERR_NOERROR)
244 devId = (UINT_PTR) i;
248 const int devcount = (
int) waveOutGetNumDevs();
250 for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
251 result = waveOutGetDevCaps(i, &caps,
sizeof (caps));
252 if (result != MMSYSERR_NOERROR)
257 devId = (UINT_PTR) i;
262 if (devId == WAVE_MAPPER) {
270 if (this->hidden ==
NULL) {
273 SDL_memset(this->hidden, 0, (
sizeof *this->hidden));
277 this->hidden->wavebuf[i].dwUser = 0xFFFF;
279 if (this->spec.channels > 2)
280 this->spec.channels = 2;
283 if (this->spec.samples < (this->spec.freq / 4))
284 this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
286 while ((!valid_datatype) && (test_format)) {
287 switch (test_format) {
292 this->spec.format = test_format;
293 if (PrepWaveFormat(
this, devId, &waveformat, iscapture)) {
306 if (!valid_datatype) {
307 WINMM_CloseDevice(
this);
316 result = waveInOpen(&this->hidden->hin, devId, &waveformat,
317 (DWORD_PTR) CaptureSound, (DWORD_PTR)
this,
320 result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
321 (DWORD_PTR) FillSound, (DWORD_PTR)
this,
325 if (result != MMSYSERR_NOERROR) {
326 WINMM_CloseDevice(
this);
327 return SetMMerror(
"waveOutOpen()", result);
334 result = waveOutGetDevCaps((
UINT) this->hidden->hout,
335 &caps,
sizeof(caps));
336 if (result != MMSYSERR_NOERROR) {
337 WINMM_CloseDevice(
this);
338 return SetMMerror(
"waveOutGetDevCaps()", result);
340 printf(
"Audio device: %s\n", caps.szPname);
345 this->hidden->audio_sem =
346 CreateSemaphore(
NULL, NUM_BUFFERS - 1, NUM_BUFFERS,
NULL);
347 if (this->hidden->audio_sem ==
NULL) {
348 WINMM_CloseDevice(
this);
353 this->hidden->mixbuf =
355 if (this->hidden->mixbuf ==
NULL) {
356 WINMM_CloseDevice(
this);
361 sizeof(this->hidden->wavebuf[i]));
362 this->hidden->wavebuf[
i].dwBufferLength = this->spec.size;
363 this->hidden->wavebuf[
i].dwFlags = WHDR_DONE;
364 this->hidden->wavebuf[
i].lpData =
365 (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
366 result = waveOutPrepareHeader(this->hidden->hout,
367 &this->hidden->wavebuf[i],
368 sizeof(this->hidden->wavebuf[i]));
369 if (result != MMSYSERR_NOERROR) {
370 WINMM_CloseDevice(
this);
371 return SetMMerror(
"waveOutPrepareHeader()", result);
395 "winmm",
"Windows Waveform Audio", WINMM_Init, 0
void(* CloseDevice)(_THIS)
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
void(* SDL_AddAudioDevice)(const char *name)
void(* WaitDevice)(_THIS)
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Uint8 *(* GetDeviceBuf)(_THIS)
DECLSPEC void SDLCALL SDL_free(void *mem)
Uint16 SDL_AudioFormat
Audio format flags.
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
AudioBootStrap WINMM_bootstrap
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
SDL_AudioFormat SDL_NextAudioFormat(void)
#define SDL_AUDIO_ISFLOAT(x)
void(* PlayDevice)(_THIS)
void(* DetectDevices)(int iscapture, SDL_AddAudioDevice addfn)
#define SDL_AUDIO_BITSIZE(x)
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
#define WIN_StringToUTF8(S)
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
DECLSPEC size_t SDLCALL SDL_strlen(const char *str)
#define SDL_OutOfMemory()
#define SDL_arraysize(array)
#define WAVE_FORMAT_IEEE_FLOAT
uint8_t Uint8
An unsigned 8-bit integer type.