Fixed a bug I introduced in waveInGetDevCapsA(WAVE_MAPPER) test.

Moved format structure array to header file and restored
NB_WIN_FORMATS macro to calculate array size.
Added more error results and used macro as suggested by Andreas Mohr.
Cleaned up error result printing to be more consistent.
This commit is contained in:
Robert Reif 2004-05-21 20:53:45 +00:00 committed by Alexandre Julliard
parent 483803ff42
commit b0d62bb73f
3 changed files with 95 additions and 86 deletions

View File

@ -35,12 +35,15 @@
static const char * wave_in_error(MMRESULT error)
{
static char msg[1024];
static char long_msg[1100];
MMRESULT rc;
rc = waveInGetErrorText(error, msg, sizeof(msg));
if (rc != MMSYSERR_NOERROR)
sprintf(msg, "waveInGetErrorText(%x) failed with error %x", error, rc);
return msg;
sprintf(long_msg, "waveInGetErrorText(%x) failed with error %x", error, rc);
else
sprintf(long_msg, "%s(%s)", mmsys_error(error), msg);
return long_msg;
}
static void wave_in_test_deviceIn(int device, int format, DWORD flags, LPWAVEINCAPS pcaps)
@ -71,9 +74,9 @@ static void wave_in_test_deviceIn(int device, int format, DWORD flags, LPWAVEINC
ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
(rc==WAVERR_BADFORMAT && (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & win_formats[format][0])) ||
(rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
"waveInOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%d(%s)\n",device,
"waveInOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%s\n",device,
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,CALLBACK_EVENT|flags,
wave_open_flags(CALLBACK_EVENT|flags),rc,wave_in_error(rc));
wave_open_flags(CALLBACK_EVENT|flags),wave_in_error(rc));
if (rc!=MMSYSERR_NOERROR) {
CloseHandle(hevent);
return;
@ -98,18 +101,18 @@ static void wave_in_test_deviceIn(int device, int format, DWORD flags, LPWAVEINC
frag.lpNext=0;
rc=waveInPrepareHeader(win, &frag, sizeof(frag));
ok(rc==MMSYSERR_NOERROR, "waveInPrepareHeader: device=%d rc=%s(%s)\n",device,mmsys_error(rc),wave_in_error(rc));
ok(rc==MMSYSERR_NOERROR, "waveInPrepareHeader: device=%d rc=%s\n",device,wave_in_error(rc));
ok(frag.dwFlags&WHDR_PREPARED,"waveInPrepareHeader: prepared flag not set\n");
if (winetest_interactive && rc==MMSYSERR_NOERROR) {
trace("Recording for 1 second at %ldx%2dx%d %04lx\n",
trace("Recording for 1 second at %5ldx%2dx%d %04lx\n",
wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels,flags);
rc=waveInAddBuffer(win, &frag, sizeof(frag));
ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer: device=%d rc=%s(%s)\n",device,mmsys_error(rc),wave_in_error(rc));
ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer: device=%d rc=%s\n",device,wave_in_error(rc));
rc=waveInStart(win);
ok(rc==MMSYSERR_NOERROR,"waveInStart: device=%d rc=%s(%s)\n",device,mmsys_error(rc),wave_in_error(rc));
ok(rc==MMSYSERR_NOERROR,"waveInStart: device=%d rc=%s\n",device,wave_in_error(rc));
res = WaitForSingleObject(hevent,1200);
ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for header\n");
@ -120,13 +123,13 @@ static void wave_in_test_deviceIn(int device, int format, DWORD flags, LPWAVEINC
if (res!=WAIT_OBJECT_0) {
rc=waveInStop(win);
ok(rc==MMSYSERR_NOERROR,
"waveInStop: device=%d rc=%s(%s)\n",device,mmsys_error(rc),wave_in_error(rc));
"waveInStop: device=%d rc=%s\n",device,wave_in_error(rc));
}
}
rc=waveInUnprepareHeader(win, &frag, sizeof(frag));
ok(rc==MMSYSERR_NOERROR,
"waveInUnprepareHeader: device=%d rc=%s(%s)\n",device,mmsys_error(rc),wave_in_error(rc));
"waveInUnprepareHeader: device=%d rc=%s\n",device,wave_in_error(rc));
waveInClose(win);
res=WaitForSingleObject(hevent,1000);
@ -151,15 +154,15 @@ static void wave_in_tests()
rc=waveInGetDevCapsA(ndev+1,&caps,sizeof(caps));
ok(rc==MMSYSERR_BADDEVICEID,
"waveInGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s(%s)\n",mmsys_error(rc),wave_in_error(rc));
"waveInGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s\n",wave_in_error(rc));
rc=waveInGetDevCapsA(WAVE_MAPPER,&caps,sizeof(caps));
if (ndev>0)
ok(rc==MMSYSERR_NOERROR,
"waveInGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc));
"waveInGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",wave_in_error(rc));
else
ok(rc==MMSYSERR_BADDEVICEID || MMSYSERR_NODRIVER,
"waveInGetDevCapsA: MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER expected, got %s\n",mmsys_error(rc));
ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER,
"waveInGetDevCapsA: MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER expected, got %s\n",wave_in_error(rc));
format.wFormatTag=WAVE_FORMAT_PCM;
format.nChannels=2;
@ -170,31 +173,30 @@ static void wave_in_tests()
format.cbSize=0;
rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL);
ok(rc==MMSYSERR_BADDEVICEID,
"waveInOpen: MMSYSERR_BADDEVICEID expected, got %s(%s)\n",mmsys_error(rc),wave_in_error(rc));
"waveInOpen: MMSYSERR_BADDEVICEID expected, got %s\n",wave_in_error(rc));
for (d=0;d<ndev;d++) {
rc=waveInGetDevCapsA(d,&caps,sizeof(caps));
ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID,
"waveInGetDevCapsA: failed to get capabilities of device %d: rc=%s(%s)\n",d,mmsys_error(rc),wave_in_error(rc));
"waveInGetDevCapsA: failed to get capabilities of device %d: rc=%s\n",d,wave_in_error(rc));
if (rc==MMSYSERR_BADDEVICEID)
continue;
name=NULL;
rc=waveInMessage((HWAVEIN)d, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0);
ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
"waveInMessage: failed to get interface size for device: %d rc=%s(%s)\n",d,mmsys_error(rc),wave_in_error(rc));
"waveInMessage: failed to get interface size for device: %d rc=%s\n",d,wave_in_error(rc));
if (rc==MMSYSERR_NOERROR) {
wname = (WCHAR *)malloc(size);
rc=waveInMessage((HWAVEIN)d, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wname, size);
ok(rc==MMSYSERR_NOERROR,"waveInMessage: failed to get interface name for device: %d rc=%s(%s)\n",d,mmsys_error(rc),wave_in_error(rc));
ok(rc==MMSYSERR_NOERROR,"waveInMessage: failed to get interface name for device: %d rc=%s\n",d,wave_in_error(rc));
ok(lstrlenW(wname)+1==size/sizeof(WCHAR),"got an incorrect size: %ld instead of %d\n",size,(lstrlenW(wname)+1)*sizeof(WCHAR));
if (rc==MMSYSERR_NOERROR) {
name = malloc(size/sizeof(WCHAR));
WideCharToMultiByte(CP_ACP, 0, wname, size/sizeof(WCHAR), name, size/sizeof(WCHAR), NULL, NULL);
}
free(wname);
}
else if (rc==MMSYSERR_NOTSUPPORTED) {
} else if (rc==MMSYSERR_NOTSUPPORTED) {
name=strdup("not supported");
}
@ -224,7 +226,7 @@ static void wave_in_tests()
oformat=format;
rc=waveInOpen(&win,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
"waveInOpen: opening the device in 11 bit mode should fail %d: rc=%s\n",d,mmsys_error(rc));
"waveInOpen: opening the device in 11 bit mode should fail %d: rc=%s\n",d,wave_in_error(rc));
if (rc==MMSYSERR_NOERROR) {
trace(" got %ldx%2dx%d for %ldx%2dx%d\n",
format.nSamplesPerSec, format.wBitsPerSample,
@ -245,7 +247,7 @@ static void wave_in_tests()
oformat=format;
rc=waveInOpen(&win,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
"waveInOpen: opening the device with 2 MHz sample rate should fail %d: rc=%s\n",d,mmsys_error(rc));
"waveInOpen: opening the device with 2 MHz sample rate should fail %d: rc=%s\n",d,wave_in_error(rc));
if (rc==MMSYSERR_NOERROR) {
trace(" got %ldx%2dx%d for %ldx%2dx%d\n",
format.nSamplesPerSec, format.wBitsPerSample,

View File

@ -32,29 +32,6 @@
#include "winmm_test.h"
const unsigned int win_formats[NB_WIN_FORMATS][4]={
{WAVE_FORMAT_1M08, 11025, 8, 1},
{WAVE_FORMAT_1S08, 11025, 8, 2},
{WAVE_FORMAT_1M16, 11025, 16, 1},
{WAVE_FORMAT_1S16, 11025, 16, 2},
{WAVE_FORMAT_2M08, 22050, 8, 1},
{WAVE_FORMAT_2S08, 22050, 8, 2},
{WAVE_FORMAT_2M16, 22050, 16, 1},
{WAVE_FORMAT_2S16, 22050, 16, 2},
{WAVE_FORMAT_4M08, 44100, 8, 1},
{WAVE_FORMAT_4S08, 44100, 8, 2},
{WAVE_FORMAT_4M16, 44100, 16, 1},
{WAVE_FORMAT_4S16, 44100, 16, 2},
{WAVE_FORMAT_48M08, 48000, 8, 1},
{WAVE_FORMAT_48S08, 48000, 8, 2},
{WAVE_FORMAT_48M16, 48000, 16, 1},
{WAVE_FORMAT_48S16, 48000, 16, 2},
{WAVE_FORMAT_96M08, 96000, 8, 1},
{WAVE_FORMAT_96S08, 96000, 8, 2},
{WAVE_FORMAT_96M16, 96000, 16, 1},
{WAVE_FORMAT_96S16, 96000, 16, 2}
};
/*
* Note that in most of this test we may get MMSYSERR_BADDEVICEID errors
* at about any time if the user starts another application that uses the
@ -98,36 +75,45 @@ static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
return buf;
}
const char* mmsys_error(MMRESULT error)
{
#define DEVTYPE_TO_STR(dev) case dev: return #dev
static char unknown[32];
switch (error) {
DEVTYPE_TO_STR(MMSYSERR_NOERROR);
DEVTYPE_TO_STR(MMSYSERR_ERROR);
DEVTYPE_TO_STR(MMSYSERR_BADDEVICEID);
DEVTYPE_TO_STR(MMSYSERR_NOTENABLED);
DEVTYPE_TO_STR(MMSYSERR_ALLOCATED);
DEVTYPE_TO_STR(MMSYSERR_INVALHANDLE);
DEVTYPE_TO_STR(MMSYSERR_NODRIVER);
DEVTYPE_TO_STR(MMSYSERR_NOMEM);
DEVTYPE_TO_STR(MMSYSERR_NOTSUPPORTED);
DEVTYPE_TO_STR(MMSYSERR_BADERRNUM);
DEVTYPE_TO_STR(MMSYSERR_INVALFLAG);
DEVTYPE_TO_STR(MMSYSERR_INVALPARAM);
DEVTYPE_TO_STR(WAVERR_BADFORMAT);
DEVTYPE_TO_STR(WAVERR_STILLPLAYING);
DEVTYPE_TO_STR(WAVERR_UNPREPARED);
DEVTYPE_TO_STR(WAVERR_SYNC);
}
sprintf(unknown, "Unknown(0x%08x)", error);
return unknown;
#undef DEVTYPE_TO_STR
}
static const char * wave_out_error(MMRESULT error)
{
static char msg[1024];
static char long_msg[1100];
MMRESULT rc;
rc = waveOutGetErrorText(error, msg, sizeof(msg));
if (rc != MMSYSERR_NOERROR)
sprintf(msg, "waveOutGetErrorText(%x) failed with error %x", error, rc);
return msg;
}
const char* mmsys_error(DWORD error)
{
static char unknown[32];
switch (error) {
case MMSYSERR_NOERROR: return "MMSYSERR_NOERROR";
case MMSYSERR_ERROR: return "MMSYSERR_ERROR";
case MMSYSERR_BADDEVICEID: return "MMSYSERR_BADDEVICEID";
case MMSYSERR_NOTENABLED: return "MMSYSERR_NOTENABLED";
case MMSYSERR_ALLOCATED: return "MMSYSERR_ALLOCATED";
case MMSYSERR_INVALHANDLE: return "MMSYSERR_INVALHANDLE";
case MMSYSERR_NODRIVER: return "MMSYSERR_NODRIVER";
case MMSYSERR_NOMEM: return "MMSYSERR_NOMEM";
case MMSYSERR_NOTSUPPORTED: return "MMSYSERR_NOTSUPPORTED";
case MMSYSERR_BADERRNUM: return "MMSYSERR_BADERRNUM";
case MMSYSERR_INVALFLAG: return "MMSYSERR_INVALFLAG";
case MMSYSERR_INVALPARAM: return "MMSYSERR_INVALPARAM";
}
sprintf(unknown, "Unknown(0x%08lx)", error);
return unknown;
sprintf(long_msg, "waveOutGetErrorText(%x) failed with error %x", error, rc);
else
sprintf(long_msg, "%s(%s)", mmsys_error(error), msg);
return long_msg;
}
const char * wave_open_flags(DWORD flags)
@ -196,7 +182,7 @@ static const char * wave_out_caps(DWORD dwSupport)
ADD_FLAG(WAVECAPS_SAMPLEACCURATE);
return msg[0] ? msg + 1 : "";
#undef FLAG
#undef ADD_FLAG
}
static void wave_out_test_deviceOut(int device, double duration, int format, DWORD flags, LPWAVEOUTCAPS pcaps)
@ -227,9 +213,9 @@ static void wave_out_test_deviceOut(int device, double duration, int format, DWO
ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
(rc==WAVERR_BADFORMAT && (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & win_formats[format][0])) ||
(rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
"waveOutOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%d(%s)\n",device,
"waveOutOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%s\n",device,
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,CALLBACK_EVENT|flags,
wave_open_flags(CALLBACK_EVENT|flags),rc,wave_out_error(rc));
wave_open_flags(CALLBACK_EVENT|flags),wave_out_error(rc));
if (rc!=MMSYSERR_NOERROR) {
CloseHandle(hevent);
return;
@ -248,30 +234,30 @@ static void wave_out_test_deviceOut(int device, double duration, int format, DWO
frag.dwLoops=0;
rc=waveOutGetVolume(wout,&volume);
ok(rc==MMSYSERR_NOERROR,"waveOutGetVolume: device=%d rc=%d\n",device,rc);
ok(rc==MMSYSERR_NOERROR,"waveOutGetVolume: device=%d rc=%s\n",device,wave_out_error(rc));
rc=waveOutPrepareHeader(wout, &frag, sizeof(frag));
ok(rc==MMSYSERR_NOERROR,
"waveOutPrepareHeader: device=%d rc=%d\n",device,rc);
"waveOutPrepareHeader: device=%d rc=%s\n",device,wave_out_error(rc));
if (winetest_interactive && rc==MMSYSERR_NOERROR) {
trace("Playing %g second 440Hz tone at %ldx%2dx%d %04lx\n",duration,
trace("Playing %g second 440Hz tone at %5ldx%2dx%d %04lx\n",duration,
wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels,flags);
rc=waveOutSetVolume(wout,0x20002000);
ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc);
ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%s\n",device,wave_out_error(rc));
WaitForSingleObject(hevent,INFINITE);
rc=waveOutWrite(wout, &frag, sizeof(frag));
ok(rc==MMSYSERR_NOERROR,"waveOutWrite: device=%d rc=%d\n",device,rc);
ok(rc==MMSYSERR_NOERROR,"waveOutWrite: device=%d rc=%s\n",device,wave_out_error(rc));
WaitForSingleObject(hevent,INFINITE);
rc=waveOutSetVolume(wout,volume);
ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc);
ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%s\n",device,wave_out_error(rc));
}
rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));
ok(rc==MMSYSERR_NOERROR,
"waveOutUnprepareHeader: device=%d rc=%d\n",device,rc);
"waveOutUnprepareHeader: device=%d rc=%s\n",device,wave_out_error(rc));
free(frag.lpData);
CloseHandle(hevent);
@ -318,18 +304,18 @@ static void wave_out_tests()
for (d=0;d<ndev;d++) {
rc=waveOutGetDevCapsA(d,&caps,sizeof(caps));
ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID,
"waveOutGetDevCapsA: failed to get capabilities of device %d: rc=%s\n",d,mmsys_error(rc));
"waveOutGetDevCapsA: failed to get capabilities of device %d: rc=%s\n",d,wave_out_error(rc));
if (rc==MMSYSERR_BADDEVICEID)
continue;
name=NULL;
rc=waveOutMessage((HWAVEOUT)d, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0);
ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
"waveOutMessage: failed to get interface size for device: %d rc=%s\n",d,mmsys_error(rc));
"waveOutMessage: failed to get interface size for device: %d rc=%s\n",d,wave_out_error(rc));
if (rc==MMSYSERR_NOERROR) {
wname = (WCHAR *)malloc(size);
rc=waveOutMessage((HWAVEOUT)d, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wname, size);
ok(rc==MMSYSERR_NOERROR,"waveOutMessage: failed to get interface name for device: %d rc=%s\n",d,mmsys_error(rc));
ok(rc==MMSYSERR_NOERROR,"waveOutMessage: failed to get interface name for device: %d rc=%s\n",d,wave_out_error(rc));
ok(lstrlenW(wname)+1==size/sizeof(WCHAR),"got an incorrect size: %ld instead of %d\n",size,(lstrlenW(wname)+1)*sizeof(WCHAR));
if (rc==MMSYSERR_NOERROR) {
name = malloc(size/sizeof(WCHAR));
@ -375,7 +361,7 @@ static void wave_out_tests()
oformat=format;
rc=waveOutOpen(&wout,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
"waveOutOpen: opening the device in 11 bits mode should fail %d: rc=%s\n",d,mmsys_error(rc));
"waveOutOpen: opening the device in 11 bits mode should fail %d: rc=%s\n",d,wave_out_error(rc));
if (rc==MMSYSERR_NOERROR) {
trace(" got %ldx%2dx%d for %ldx%2dx%d\n",
format.nSamplesPerSec, format.wBitsPerSample,
@ -396,7 +382,7 @@ static void wave_out_tests()
oformat=format;
rc=waveOutOpen(&wout,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
"waveOutOpen: opening the device at 2 MHz sample rate should fail %d: rc=%s\n",d,mmsys_error(rc));
"waveOutOpen: opening the device at 2 MHz sample rate should fail %d: rc=%s\n",d,wave_out_error(rc));
if (rc==MMSYSERR_NOERROR) {
trace(" got %ldx%2dx%d for %ldx%2dx%d\n",
format.nSamplesPerSec, format.wBitsPerSample,

View File

@ -27,8 +27,29 @@
#define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */
#endif
#define NB_WIN_FORMATS 20
extern const unsigned int win_formats[NB_WIN_FORMATS][4];
static const unsigned int win_formats[][4] = {
{WAVE_FORMAT_1M08, 11025, 8, 1},
{WAVE_FORMAT_1S08, 11025, 8, 2},
{WAVE_FORMAT_1M16, 11025, 16, 1},
{WAVE_FORMAT_1S16, 11025, 16, 2},
{WAVE_FORMAT_2M08, 22050, 8, 1},
{WAVE_FORMAT_2S08, 22050, 8, 2},
{WAVE_FORMAT_2M16, 22050, 16, 1},
{WAVE_FORMAT_2S16, 22050, 16, 2},
{WAVE_FORMAT_4M08, 44100, 8, 1},
{WAVE_FORMAT_4S08, 44100, 8, 2},
{WAVE_FORMAT_4M16, 44100, 16, 1},
{WAVE_FORMAT_4S16, 44100, 16, 2},
{WAVE_FORMAT_48M08, 48000, 8, 1},
{WAVE_FORMAT_48S08, 48000, 8, 2},
{WAVE_FORMAT_48M16, 48000, 16, 1},
{WAVE_FORMAT_48S16, 48000, 16, 2},
{WAVE_FORMAT_96M08, 96000, 8, 1},
{WAVE_FORMAT_96S08, 96000, 8, 2},
{WAVE_FORMAT_96M16, 96000, 16, 1},
{WAVE_FORMAT_96S16, 96000, 16, 2}
};
#define NB_WIN_FORMATS (sizeof(win_formats)/sizeof(*win_formats))
extern const char* wave_open_flags(DWORD);
extern const char* mmsys_error(DWORD);
extern const char* mmsys_error(MMRESULT);