-- v2: wineswmidi: Initialize DirectMusic when opening the device. wineswmidi: Handle MODM_OPEN and MODM_CLOSE.
From: Anton Baskanov baskanov@gmail.com
--- dlls/winmm/winmm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c index 73050e0affb..a99c8c4ffe8 100644 --- a/dlls/winmm/winmm.c +++ b/dlls/winmm/winmm.c @@ -1392,7 +1392,7 @@ MMRESULT WINAPI midiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID, mosm.wDeviceID = *lpuDeviceID; lpwm = MIDI_OutAlloc(&hMidiOut, &dwCallback, &dwInstance, &fdwOpen, 1, &mosm); if (!lpwm) { - free(lpMidiStrm); + wine_midi_stream_free(lpMidiStrm); return MMSYSERR_NOMEM; } lpMidiStrm->hDevice = hMidiOut; @@ -1404,7 +1404,7 @@ MMRESULT WINAPI midiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID, ret = MMDRV_Open(&lpwm->mld, MODM_OPEN, (DWORD_PTR)&lpwm->mod, CALLBACK_NULL); if (ret != MMSYSERR_NOERROR) { MMDRV_Free(hMidiOut, &lpwm->mld); - free(lpMidiStrm); + wine_midi_stream_free(lpMidiStrm); return ret; }
From: Anton Baskanov baskanov@gmail.com
--- configure | 2 + configure.ac | 1 + dlls/wineswmidi/Makefile.in | 4 ++ dlls/wineswmidi/swmidi.c | 72 +++++++++++++++++++++++++++++++++ dlls/wineswmidi/wineswmidi.spec | 3 ++ dlls/winmm/lolvldrv.c | 1 + dlls/winmm/tests/midi.c | 5 ++- 7 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 dlls/wineswmidi/Makefile.in create mode 100644 dlls/wineswmidi/swmidi.c create mode 100644 dlls/wineswmidi/wineswmidi.spec
diff --git a/configure b/configure index 928f3430e4b..b5b10ee52c4 100755 --- a/configure +++ b/configure @@ -1527,6 +1527,7 @@ enable_winemapi enable_wineoss_drv enable_wineps_drv enable_winepulse_drv +enable_wineswmidi enable_wineusb_sys enable_winevulkan enable_winewayland_drv @@ -22935,6 +22936,7 @@ wine_fn_config_makefile dlls/wineoss.drv enable_wineoss_drv wine_fn_config_makefile dlls/wineps.drv enable_wineps_drv wine_fn_config_makefile dlls/wineps16.drv16 enable_win16 wine_fn_config_makefile dlls/winepulse.drv enable_winepulse_drv +wine_fn_config_makefile dlls/wineswmidi enable_wineswmidi wine_fn_config_makefile dlls/wineusb.sys enable_wineusb_sys wine_fn_config_makefile dlls/winevulkan enable_winevulkan wine_fn_config_makefile dlls/winewayland.drv enable_winewayland_drv diff --git a/configure.ac b/configure.ac index 5f9e63b6f9f..a9ed473e727 100644 --- a/configure.ac +++ b/configure.ac @@ -3274,6 +3274,7 @@ WINE_CONFIG_MAKEFILE(dlls/wineoss.drv) WINE_CONFIG_MAKEFILE(dlls/wineps.drv) WINE_CONFIG_MAKEFILE(dlls/wineps16.drv16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/winepulse.drv) +WINE_CONFIG_MAKEFILE(dlls/wineswmidi) WINE_CONFIG_MAKEFILE(dlls/wineusb.sys) WINE_CONFIG_MAKEFILE(dlls/winevulkan) WINE_CONFIG_MAKEFILE(dlls/winewayland.drv) diff --git a/dlls/wineswmidi/Makefile.in b/dlls/wineswmidi/Makefile.in new file mode 100644 index 00000000000..26acbef4b9b --- /dev/null +++ b/dlls/wineswmidi/Makefile.in @@ -0,0 +1,4 @@ +MODULE = wineswmidi.dll + +SOURCES = \ + swmidi.c diff --git a/dlls/wineswmidi/swmidi.c b/dlls/wineswmidi/swmidi.c new file mode 100644 index 00000000000..ab098a21f2e --- /dev/null +++ b/dlls/wineswmidi/swmidi.c @@ -0,0 +1,72 @@ +/* + * MIDI driver for software synthesizer + * + * Copyright 2025 Anton Baskanov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#include "windef.h" +#include "mmddk.h" +#include "mmdeviceapi.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(midi); + +DWORD WINAPI swmidi_modMessage(UINT dev_id, UINT msg, DWORD_PTR user, DWORD_PTR param1, + DWORD_PTR param2) +{ + TRACE("dev_id %u, msg %x, user %#Ix, param1 %#Ix, param2 %#Ix.\n", dev_id, msg, user, param1, + param2); + + switch (msg) + { + case DRVM_INIT: + case DRVM_EXIT: + return MMSYSERR_NOERROR; + case MODM_GETNUMDEVS: + return 1; + } + + return MMSYSERR_NOTSUPPORTED; +} + +LRESULT CALLBACK swmidi_DriverProc(DWORD_PTR dev_id, HDRVR drvr, UINT msg, LPARAM param1, + LPARAM param2) +{ + TRACE("dev_id %Iu, drvr %p, msg %x, param1 %#Ix, param2 %#Ix.\n", dev_id, drvr, msg, param1, + param2); + + switch(msg) + { + case DRV_LOAD: + case DRV_FREE: + case DRV_OPEN: + case DRV_CLOSE: + case DRV_ENABLE: + case DRV_DISABLE: + case DRV_QUERYCONFIGURE: + return DRV_SUCCESS; + case DRV_CONFIGURE: + case DRV_INSTALL: + case DRV_REMOVE: + return DRVCNF_OK; + } + + return DRV_FAILURE; +} diff --git a/dlls/wineswmidi/wineswmidi.spec b/dlls/wineswmidi/wineswmidi.spec new file mode 100644 index 00000000000..03b701e95c8 --- /dev/null +++ b/dlls/wineswmidi/wineswmidi.spec @@ -0,0 +1,3 @@ +# WinMM driver functions +@ stdcall -private DriverProc(long long long long long) swmidi_DriverProc +@ stdcall -private modMessage(long long long long long) swmidi_modMessage diff --git a/dlls/winmm/lolvldrv.c b/dlls/winmm/lolvldrv.c index e664021dc64..cf61fbce06d 100644 --- a/dlls/winmm/lolvldrv.c +++ b/dlls/winmm/lolvldrv.c @@ -538,6 +538,7 @@ static void MMDRV_Init(void) free(drvA); PropVariantClear(&pv);
+ MMDRV_Install("swmidi", "wineswmidi.dll", FALSE); MMDRV_Install("wavemapper", "msacm32.drv", TRUE); MMDRV_Install("midimapper", "midimap.dll", TRUE);
diff --git a/dlls/winmm/tests/midi.c b/dlls/winmm/tests/midi.c index 70a5375f1cb..8be1ace09fc 100644 --- a/dlls/winmm/tests/midi.c +++ b/dlls/winmm/tests/midi.c @@ -279,9 +279,12 @@ static void test_midiOut_device(UINT udev, HWND hwnd) DWORD ovolume; UINT udevid; MIDIHDR mhdr; + BOOL swmidi; + + swmidi = udev == midiOutGetNumDevs() - 1;
rc = midiOutGetDevCapsA(udev, &capsA, sizeof(capsA)); - ok(!rc, "midiOutGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc)); if (!rc) { trace("* %s: manufacturer=%d, product=%d, tech=%d, support=%lX: %d voices, %d notes\n", capsA.szPname, capsA.wMid, capsA.wPid, capsA.wTechnology, capsA.dwSupport, capsA.wVoices, capsA.wNotes);
From: Anton Baskanov baskanov@gmail.com
--- dlls/wineswmidi/swmidi.c | 21 +++++++++++++++++++++ dlls/winmm/tests/midi.c | 5 +---- include/mmsystem.h | 2 ++ 3 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/dlls/wineswmidi/swmidi.c b/dlls/wineswmidi/swmidi.c index ab098a21f2e..038aa269ec6 100644 --- a/dlls/wineswmidi/swmidi.c +++ b/dlls/wineswmidi/swmidi.c @@ -28,6 +28,25 @@
WINE_DEFAULT_DEBUG_CHANNEL(midi);
+static DWORD swmidi_get_dev_caps(MIDIOUTCAPSW *out_caps, DWORD_PTR size) +{ + MIDIOUTCAPSW caps = { + MM_MICROSOFT, MM_MSFT_WDMAUDIO_MIDIOUT, 0x050a, + L"Wine GS Wavetable SW Synth", + MOD_SWSYNTH, 48, 48, 0xffff, + MIDICAPS_VOLUME | MIDICAPS_LRVOLUME, + }; + + TRACE("out_caps %p, size %Iu.\n", out_caps, size); + + if (!out_caps) + return MMSYSERR_INVALPARAM; + + memcpy(out_caps, &caps, min(size, sizeof(caps))); + + return MMSYSERR_NOERROR; +} + DWORD WINAPI swmidi_modMessage(UINT dev_id, UINT msg, DWORD_PTR user, DWORD_PTR param1, DWORD_PTR param2) { @@ -41,6 +60,8 @@ DWORD WINAPI swmidi_modMessage(UINT dev_id, UINT msg, DWORD_PTR user, DWORD_PTR return MMSYSERR_NOERROR; case MODM_GETNUMDEVS: return 1; + case MODM_GETDEVCAPS: + return swmidi_get_dev_caps((MIDIOUTCAPSW *)param1, param2); }
return MMSYSERR_NOTSUPPORTED; diff --git a/dlls/winmm/tests/midi.c b/dlls/winmm/tests/midi.c index 8be1ace09fc..70a5375f1cb 100644 --- a/dlls/winmm/tests/midi.c +++ b/dlls/winmm/tests/midi.c @@ -279,12 +279,9 @@ static void test_midiOut_device(UINT udev, HWND hwnd) DWORD ovolume; UINT udevid; MIDIHDR mhdr; - BOOL swmidi; - - swmidi = udev == midiOutGetNumDevs() - 1;
rc = midiOutGetDevCapsA(udev, &capsA, sizeof(capsA)); - todo_wine_if(swmidi) ok(!rc, "midiOutGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc)); + ok(!rc, "midiOutGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc)); if (!rc) { trace("* %s: manufacturer=%d, product=%d, tech=%d, support=%lX: %d voices, %d notes\n", capsA.szPname, capsA.wMid, capsA.wPid, capsA.wTechnology, capsA.dwSupport, capsA.wVoices, capsA.wNotes); diff --git a/include/mmsystem.h b/include/mmsystem.h index a80716ef949..c65f627c0ed 100644 --- a/include/mmsystem.h +++ b/include/mmsystem.h @@ -265,6 +265,8 @@ typedef void (CALLBACK *LPDRVCALLBACK)(HDRVR,UINT,DWORD_PTR,DWORD_PTR,DWORD_PTR)
#define MM_PC_JOYSTICK 12 /* Joystick adapter */
+#define MM_MSFT_WDMAUDIO_MIDIOUT 102 + #define MM_CREATIVE_SBP16_WAVEOUT 104
WINMMAPI UINT WINAPI mmsystemGetVersion(void);
From: Anton Baskanov baskanov@gmail.com
--- dlls/winmm/tests/midi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winmm/tests/midi.c b/dlls/winmm/tests/midi.c index 70a5375f1cb..8f74208266c 100644 --- a/dlls/winmm/tests/midi.c +++ b/dlls/winmm/tests/midi.c @@ -903,7 +903,7 @@ static void test_midiStream(UINT udev, HWND hwnd) rc = midiStreamProperty(hm, (void*)&midiprop, MIDIPROP_SET | MIDIPROP_TIMEDIV); ok(rc == MMSYSERR_INVALPARAM, "midiStreamProperty(SET|TIMEDIV, dev=%d) rc=%s\n", udev, mmsys_error(rc));
- ret = WaitForSingleObject(records.done, INFINITE); + ret = WaitForSingleObject(records.done, 3000); ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed, got %ld\n", ret);
rc = midiStreamPause(hm);
From: Anton Baskanov baskanov@gmail.com
--- dlls/wineswmidi/Makefile.in | 1 + dlls/wineswmidi/swmidi.c | 76 +++++++++++- dlls/winmm/tests/midi.c | 228 +++++++++++++++++++----------------- 3 files changed, 194 insertions(+), 111 deletions(-)
diff --git a/dlls/wineswmidi/Makefile.in b/dlls/wineswmidi/Makefile.in index 26acbef4b9b..5e9a8995868 100644 --- a/dlls/wineswmidi/Makefile.in +++ b/dlls/wineswmidi/Makefile.in @@ -1,4 +1,5 @@ MODULE = wineswmidi.dll +DELAYIMPORTS = winmm
SOURCES = \ swmidi.c diff --git a/dlls/wineswmidi/swmidi.c b/dlls/wineswmidi/swmidi.c index 038aa269ec6..f203ad1221a 100644 --- a/dlls/wineswmidi/swmidi.c +++ b/dlls/wineswmidi/swmidi.c @@ -28,6 +28,35 @@
WINE_DEFAULT_DEBUG_CHANNEL(midi);
+struct swmidi +{ + CRITICAL_SECTION cs; + + BOOL open; + MIDIOPENDESC open_desc; + WORD flags; +}; + +static struct swmidi swmidi; + +static DWORD swmidi_init(void) +{ + TRACE("\n"); + + InitializeCriticalSection(&swmidi.cs); + + return MMSYSERR_NOERROR; +} + +static DWORD swmidi_exit(void) +{ + TRACE("\n"); + + DeleteCriticalSection(&swmidi.cs); + + return MMSYSERR_NOERROR; +} + static DWORD swmidi_get_dev_caps(MIDIOUTCAPSW *out_caps, DWORD_PTR size) { MIDIOUTCAPSW caps = { @@ -47,6 +76,46 @@ static DWORD swmidi_get_dev_caps(MIDIOUTCAPSW *out_caps, DWORD_PTR size) return MMSYSERR_NOERROR; }
+static DWORD swmidi_open(MIDIOPENDESC *desc, UINT flags) +{ + TRACE("desc %p, flags %x.\n", desc, flags); + + EnterCriticalSection(&swmidi.cs); + + if (swmidi.open) + { + LeaveCriticalSection(&swmidi.cs); + return MMSYSERR_ALLOCATED; + } + + swmidi.open = TRUE; + swmidi.open_desc = *desc; + swmidi.flags = HIWORD(flags & CALLBACK_TYPEMASK); + + LeaveCriticalSection(&swmidi.cs); + + DriverCallback(swmidi.open_desc.dwCallback, swmidi.flags, (HDRVR)swmidi.open_desc.hMidi, + MOM_OPEN, swmidi.open_desc.dwInstance, 0, 0); + + return MMSYSERR_NOERROR; +} + +static DWORD swmidi_close(void) +{ + TRACE("\n"); + + EnterCriticalSection(&swmidi.cs); + + swmidi.open = FALSE; + + LeaveCriticalSection(&swmidi.cs); + + DriverCallback(swmidi.open_desc.dwCallback, swmidi.flags, (HDRVR)swmidi.open_desc.hMidi, + MOM_CLOSE, swmidi.open_desc.dwInstance, 0, 0); + + return MMSYSERR_NOERROR; +} + DWORD WINAPI swmidi_modMessage(UINT dev_id, UINT msg, DWORD_PTR user, DWORD_PTR param1, DWORD_PTR param2) { @@ -56,12 +125,17 @@ DWORD WINAPI swmidi_modMessage(UINT dev_id, UINT msg, DWORD_PTR user, DWORD_PTR switch (msg) { case DRVM_INIT: + return swmidi_init(); case DRVM_EXIT: - return MMSYSERR_NOERROR; + return swmidi_exit(); case MODM_GETNUMDEVS: return 1; case MODM_GETDEVCAPS: return swmidi_get_dev_caps((MIDIOUTCAPSW *)param1, param2); + case MODM_OPEN: + return swmidi_open((MIDIOPENDESC *)param1, param2); + case MODM_CLOSE: + return swmidi_close(); }
return MMSYSERR_NOTSUPPORTED; diff --git a/dlls/winmm/tests/midi.c b/dlls/winmm/tests/midi.c index 8f74208266c..4789be22ac4 100644 --- a/dlls/winmm/tests/midi.c +++ b/dlls/winmm/tests/midi.c @@ -65,8 +65,8 @@ static void CALLBACK callback_func(HWAVEOUT hwo, UINT uMsg, cbinst = dwInstance; /* MYCBINST, see midiOut/StreamOpen */ }
-#define test_notification(hwnd, command, m1, p2) test_notification_dbg(hwnd, command, m1, p2, __LINE__) -static void test_notification_dbg(HWND hwnd, const char* command, UINT m1, DWORD_PTR p2, int line) +#define test_notification(hwnd, command, m1, p2, todo) test_notification_dbg(hwnd, command, m1, p2, todo, __LINE__) +static void test_notification_dbg(HWND hwnd, const char* command, UINT m1, DWORD_PTR p2, BOOL todo, int line) { /* Use message type 0 as meaning no message */ MSG msg; if (hwnd) { @@ -82,16 +82,16 @@ static void test_notification_dbg(HWND hwnd, const char* command, UINT m1, DWORD trace_(__FILE__,line)("Waiting for delayed message %x from %s\n", m1, command); SetLastError(0xDEADBEEF); rc = MsgWaitForMultipleObjects(0, NULL, FALSE, 3000, QS_POSTMESSAGE); - ok_(__FILE__,line)(rc==WAIT_OBJECT_0, "Wait failed: %04lx %ld\n", rc, GetLastError()); + todo_wine_if(todo && rc != WAIT_OBJECT_0) ok_(__FILE__,line)(rc==WAIT_OBJECT_0, "Wait failed: %04lx %ld\n", rc, GetLastError()); seen = PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE); } if (seen) { trace_(__FILE__,line)("Message %x, wParam=%Ix, lParam=%Ix from %s\n", msg.message, msg.wParam, msg.lParam, command); - ok_(__FILE__,line)(msg.hwnd==hwnd, "Didn't get the handle to our test window\n"); - ok_(__FILE__,line)(msg.message==m1 && msg.lParam==p2, "bad message %x/%Ix from %s, expect %x/%Ix\n", msg.message, msg.lParam, command, m1, p2); + todo_wine_if(todo) ok_(__FILE__,line)(msg.hwnd==hwnd, "Didn't get the handle to our test window\n"); + todo_wine_if(todo) ok_(__FILE__,line)(msg.message==m1 && msg.lParam==p2, "bad message %x/%Ix from %s, expect %x/%Ix\n", msg.message, msg.lParam, command, m1, p2); } - else ok_(__FILE__,line)(m1==0, "Expect message %x from %s\n", m1, command); + else todo_wine_if(todo) ok_(__FILE__,line)(m1==0, "Expect message %x from %s\n", m1, command); } else { /* FIXME: MOM_POSITIONCB and MOM_DONE are so close that a queue is needed. */ @@ -129,7 +129,7 @@ static void test_midiIn_device(UINT udev, HWND hwnd) "midiInOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc)); if (rc) return;
- test_notification(hwnd, "midiInOpen", MIM_OPEN, 0); + test_notification(hwnd, "midiInOpen", MIM_OPEN, 0, FALSE);
memset(&mhdr, 0, sizeof(mhdr)); mhdr.dwFlags = MHDR_DONE; @@ -192,7 +192,7 @@ static void test_midiIn_device(UINT udev, HWND hwnd) } rc = midiInReset(hm); /* Return any pending buffer */ ok(!rc, "midiInReset rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiInReset", MIM_LONGDATA, (DWORD_PTR)&mhdr); + test_notification(hwnd, "midiInReset", MIM_LONGDATA, (DWORD_PTR)&mhdr, FALSE);
ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE), "dwFlags=%lx\n", mhdr.dwFlags); rc = midiInUnprepareHeader(hm, &mhdr, sizeof(mhdr)); @@ -205,8 +205,8 @@ static void test_midiIn_device(UINT udev, HWND hwnd)
ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %Ix\n", mhdr.dwUser); free(mhdr.lpData); - test_notification(hwnd, "midiInClose", MIM_CLOSE, 0); - test_notification(hwnd, "midiIn over", 0, WHATEVER); + test_notification(hwnd, "midiInClose", MIM_CLOSE, 0, FALSE); + test_notification(hwnd, "midiIn over", 0, WHATEVER, FALSE); }
static void test_midi_infns(HWND hwnd) @@ -279,6 +279,11 @@ static void test_midiOut_device(UINT udev, HWND hwnd) DWORD ovolume; UINT udevid; MIDIHDR mhdr; + BOOL swmidi; + BOOL swmidi_mapper; + + swmidi = udev == midiOutGetNumDevs() - 1; + swmidi_mapper = midiOutGetNumDevs() == 1;
rc = midiOutGetDevCapsA(udev, &capsA, sizeof(capsA)); ok(!rc, "midiOutGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc)); @@ -305,10 +310,10 @@ static void test_midiOut_device(UINT udev, HWND hwnd) ok(!rc, "midiOutOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc)); if (rc) return;
- test_notification(hwnd, "midiOutOpen", MOM_OPEN, 0); + test_notification(hwnd, "midiOutOpen", MOM_OPEN, 0, FALSE);
rc = midiOutGetVolume(hm, &ovolume); - ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume rc=%s\n", mmsys_error(rc)); /* The native mapper responds with FFFFFFFF initially, * real devices with the volume GUI SW-synth settings. */ if (!rc) trace("Current volume %lx on device %d\n", ovolume, udev); @@ -316,10 +321,10 @@ static void test_midiOut_device(UINT udev, HWND hwnd) /* The W95 ESFM Synthesis device reports NOTENABLED although * GetVolume by handle works and music plays. */ rc = midiOutGetVolume(UlongToHandle(udev), &ovolume); - ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR || broken(rc==MMSYSERR_NOTENABLED) : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume(dev=%d) rc=%s\n", udev, mmsys_error(rc)); + todo_wine_if(swmidi) ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR || broken(rc==MMSYSERR_NOTENABLED) : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume(dev=%d) rc=%s\n", udev, mmsys_error(rc));
rc = midiOutGetVolume(hm, NULL); - ok(rc==MMSYSERR_INVALPARAM, "midiOutGetVolume NULL rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(rc==MMSYSERR_INVALPARAM, "midiOutGetVolume NULL rc=%s\n", mmsys_error(rc));
/* Tests with midiOutSetvolume show that the midi mapper forwards * the value to the real device, but Get initially always reports @@ -349,7 +354,7 @@ static void test_midiOut_device(UINT udev, HWND hwnd) { DWORD e = 0x006F4893; /* velocity, note (#69 would be 440Hz) channel */ trace("ShortMsg type %x\n", LOBYTE(LOWORD(e))); rc = midiOutShortMsg(hm, e); - ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi || swmidi_mapper) ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc)); if (!rc) Sleep(400); /* Hear note */ }
@@ -362,41 +367,41 @@ static void test_midiOut_device(UINT udev, HWND hwnd) ok(mhdr.lpData!=NULL, "No %ld bytes of memory!\n", mhdr.dwBufferLength); if (mhdr.lpData) { rc = midiOutLongMsg(hm, &mhdr, sizeof(mhdr)); - ok(rc==MIDIERR_UNPREPARED, "midiOutLongMsg unprepared rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(rc==MIDIERR_UNPREPARED, "midiOutLongMsg unprepared rc=%s\n", mmsys_error(rc)); ok(mhdr.dwFlags == MHDR_DONE, "dwFlags=%lx\n", mhdr.dwFlags); - test_notification(hwnd, "midiOutLong unprepared", 0, WHATEVER); + test_notification(hwnd, "midiOutLong unprepared", 0, WHATEVER, FALSE);
rc = midiOutPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset)-1); - ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc)); ok(mhdr.dwFlags == MHDR_DONE, "dwFlags=%lx\n", mhdr.dwFlags);
/* Since at least w2k, midiOutPrepare clears the DONE and INQUEUE flags. w95 didn't. */ /* mhdr.dwFlags |= MHDR_INQUEUE; would cause w95 to return STILLPLAYING from Unprepare */ rc = midiOutPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset)); - ok(!rc, "midiOutPrepare old size rc=%s\n", mmsys_error(rc)); - ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE)/*w9x*/ || - mhdr.dwFlags == MHDR_PREPARED, "dwFlags=%lx\n", mhdr.dwFlags); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepare old size rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE)/*w9x*/ || + mhdr.dwFlags == MHDR_PREPARED, "dwFlags=%lx\n", mhdr.dwFlags); trace("MIDIHDR flags=%lx when unsent\n", mhdr.dwFlags);
/* No flag is cleared when already prepared. */ mhdr.dwFlags |= MHDR_DONE|MHDR_INQUEUE; rc = midiOutPrepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepare rc=%s\n", mmsys_error(rc)); - ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE|MHDR_INQUEUE), "dwFlags=%lx\n", mhdr.dwFlags); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE|MHDR_INQUEUE), "dwFlags=%lx\n", mhdr.dwFlags);
mhdr.dwFlags |= MHDR_INQUEUE; rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(rc==MIDIERR_STILLPLAYING, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); - ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE|MHDR_INQUEUE), "dwFlags=%lx\n", mhdr.dwFlags); + todo_wine_if(swmidi) ok(rc==MIDIERR_STILLPLAYING, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(mhdr.dwFlags == (MHDR_PREPARED|MHDR_DONE|MHDR_INQUEUE), "dwFlags=%lx\n", mhdr.dwFlags);
mhdr.dwFlags &= ~MHDR_INQUEUE; rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); ok(mhdr.dwFlags == MHDR_DONE, "dwFlags=%lx\n", mhdr.dwFlags);
mhdr.dwFlags |= MHDR_INQUEUE; rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); ok(mhdr.dwFlags == (MHDR_INQUEUE|MHDR_DONE), "dwFlags=%lx\n", mhdr.dwFlags);
free(mhdr.lpData); @@ -409,26 +414,26 @@ static void test_midiOut_device(UINT udev, HWND hwnd) if(!rc) ok(udevid==udev, "midiOutGetID gives %d, expect %d\n", udevid, udev);
rc = midiOutReset(hm); /* Quiet everything */ - ok(!rc, "midiOutReset rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi || swmidi_mapper) ok(!rc, "midiOutReset rc=%s\n", mmsys_error(rc));
rc = midiOutClose(hm); ok(!rc, "midiOutClose rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiOutClose", MOM_CLOSE, 0); + test_notification(hwnd, "midiOutClose", MOM_CLOSE, 0, FALSE);
rc = midiOutOpen(&hm, udev, 0, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW); /* w95 broken(rc==MMSYSERR_INVALPARAM) see WINMM_CheckCallback */ ok(!rc, "midiOutOpen(dev=%d) 0 CALLBACK_WINDOW rc=%s\n", udev, mmsys_error(rc)); /* PostMessage(hwnd=0) redirects to PostThreadMessage(GetCurrentThreadId()) * which PeekMessage((HWND)-1) queries. */ - test_notification((HWND)-1, "midiOutOpen WINDOW->THREAD", 0, WHATEVER); - test_notification(hwnd, "midiOutOpen WINDOW", 0, WHATEVER); + test_notification((HWND)-1, "midiOutOpen WINDOW->THREAD", 0, WHATEVER, FALSE); + test_notification(hwnd, "midiOutOpen WINDOW", 0, WHATEVER, FALSE); if (!rc) { rc = midiOutClose(hm); ok(!rc, "midiOutClose rc=%s\n", mmsys_error(rc)); - test_notification((HWND)-1, "midiOutClose WINDOW->THREAD", 0, WHATEVER); - test_notification(hwnd, "midiOutClose", 0, WHATEVER); + test_notification((HWND)-1, "midiOutClose WINDOW->THREAD", 0, WHATEVER, FALSE); + test_notification(hwnd, "midiOutClose", 0, WHATEVER, FALSE); } - test_notification(hwnd, "midiOut over", 0, WHATEVER); + test_notification(hwnd, "midiOut over", 0, WHATEVER, FALSE); if (!strncmp(capsA.szPname, fluidsynth_prefix, strlen(fluidsynth_prefix)) || (udev == MIDIMAPPER && found_fluidsynth)) { found_fluidsynth = TRUE; @@ -441,55 +446,55 @@ static void test_midiOut_device(UINT udev, HWND hwnd) else rc = midiOutOpen(&hm, udev, (DWORD_PTR)callback_func, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION); ok(!rc, "midiOutOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc)); - test_notification(hwnd, "midiOutOpen", MOM_OPEN, 0); + test_notification(hwnd, "midiOutOpen", MOM_OPEN, 0, FALSE);
memset(&mhdr, 0, sizeof(mhdr)); mhdr.lpData = (LPSTR)SysEx_reset; mhdr.dwBufferLength = sizeof(SysEx_reset); rc = midiOutPrepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepareHeader rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepareHeader rc=%s\n", mmsys_error(rc)); rc = midiOutLongMsg(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutLongMsg rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi || swmidi_mapper) ok(!rc, "midiOutLongMsg rc=%s\n", mmsys_error(rc)); rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiOutLongMsg", MOM_DONE, (DWORD_PTR)&mhdr); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + test_notification(hwnd, "midiOutLongMsg", MOM_DONE, (DWORD_PTR)&mhdr, swmidi); Sleep(60);
mhdr.lpData = (LPSTR)SysEx_volume_off; mhdr.dwBufferLength = sizeof(SysEx_volume_off); rc = midiOutPrepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepareHeader rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepareHeader rc=%s\n", mmsys_error(rc)); rc = midiOutLongMsg(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutLongMsg rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi || swmidi_mapper) ok(!rc, "midiOutLongMsg rc=%s\n", mmsys_error(rc)); rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiOutLongMsg", MOM_DONE, (DWORD_PTR)&mhdr); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + test_notification(hwnd, "midiOutLongMsg", MOM_DONE, (DWORD_PTR)&mhdr, swmidi);
{ DWORD e = 0x006F4593; /* velocity 111, note #69, channel 4 */ trace("ShortMsg type %x (muted)\n", LOBYTE(LOWORD(e))); rc = midiOutShortMsg(hm, e); - ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi || swmidi_mapper) ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc)); /* We can't hear this voice due to volume settings */ if (!rc) Sleep(200);
rc = midiOutShortMsg(hm, 0x00004593); /* velocity 0 */ - ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi || swmidi_mapper) ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc)); }
mhdr.lpData = (LPSTR)SysEx_volume_full; mhdr.dwBufferLength = sizeof(SysEx_volume_full); rc = midiOutPrepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepareHeader rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepareHeader rc=%s\n", mmsys_error(rc)); rc = midiOutLongMsg(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutLongMsg rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi || swmidi_mapper) ok(!rc, "midiOutLongMsg rc=%s\n", mmsys_error(rc)); rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiOutLongMsg", MOM_DONE, (DWORD_PTR)&mhdr); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + test_notification(hwnd, "midiOutLongMsg", MOM_DONE, (DWORD_PTR)&mhdr, swmidi);
rc = midiOutClose(hm); ok(!rc, "midiOutClose rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiOuClose", MOM_CLOSE, 0); + test_notification(hwnd, "midiOuClose", MOM_CLOSE, 0, FALSE); }
static void test_position(HMIDISTRM hm, UINT typein, UINT typeout) @@ -608,6 +613,9 @@ static void test_midiStream(UINT udev, HWND hwnd) const DWORD MARGIN = 50; struct time_stamp_records records; MIDIOUTCAPSA capsA; + BOOL swmidi; + + swmidi = udev == midiOutGetNumDevs() - 1;
if (hwnd) rc = midiStreamOpen(&hm, &udev, 1, (DWORD_PTR)hwnd, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW); @@ -621,7 +629,7 @@ static void test_midiStream(UINT udev, HWND hwnd) ok(!rc, "midiStreamOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc)); if (rc) return;
- test_notification(hwnd, "midiStreamOpen", MOM_OPEN, 0); + test_notification(hwnd, "midiStreamOpen", MOM_OPEN, 0, FALSE);
midiprop.tempo.cbStruct = sizeof(midiprop.tempo); rc = midiStreamProperty(hm, (void*)&midiprop, MIDIPROP_GET|MIDIPROP_TEMPO); @@ -641,18 +649,18 @@ static void test_midiStream(UINT udev, HWND hwnd) mhdr.lpData = (LPSTR)&strmEvents[0]; if (mhdr.lpData) { rc = midiOutLongMsg((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(rc==MIDIERR_UNPREPARED, "midiOutLongMsg unprepared rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiOutLong unprepared", 0, WHATEVER); + todo_wine_if(swmidi) ok(rc==MIDIERR_UNPREPARED, "midiOutLongMsg unprepared rc=%s\n", mmsys_error(rc)); + test_notification(hwnd, "midiOutLong unprepared", 0, WHATEVER, FALSE);
rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset)-1); - ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc)); rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepare size rc=%s\n", mmsys_error(rc)); - ok(mhdr.dwFlags & MHDR_PREPARED, "MHDR.dwFlags when prepared %lx\n", mhdr.dwFlags); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepare size rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(mhdr.dwFlags & MHDR_PREPARED, "MHDR.dwFlags when prepared %lx\n", mhdr.dwFlags);
/* The device is still in paused mode and should queue the message. */ rc = midiStreamOut(hm, &mhdr, offsetof(MIDIHDR,dwOffset)); - ok(!rc, "midiStreamOut old size rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiStreamOut old size rc=%s\n", mmsys_error(rc)); rc2 = rc; trace("MIDIHDR flags=%lx when submitted\n", mhdr.dwFlags); /* w9X/me does not set MHDR_ISSTRM when StreamOut exits, @@ -660,7 +668,7 @@ static void test_midiStream(UINT udev, HWND hwnd)
Sleep(90); /* Wine <1.1.39 started playing immediately */ - test_notification(hwnd, "midiStream still paused", 0, WHATEVER); + test_notification(hwnd, "midiStream still paused", 0, WHATEVER, FALSE);
/* MSDN asks to use midiStreamRestart prior to midiStreamOut() * because the starting state is 'pause', but some apps seem to @@ -676,26 +684,26 @@ static void test_midiStream(UINT udev, HWND hwnd) } /* Checking INQUEUE is not the recommended way to wait for the end of a job, but we're testing. */ /* MHDR_ISSTRM is not necessarily set when midiStreamOut returns * rather than when the queue is eventually processed. */ - ok(mhdr.dwFlags & MHDR_ISSTRM, "MHDR.dwFlags %lx no ISSTRM when out of queue\n", mhdr.dwFlags); + todo_wine_if(swmidi) ok(mhdr.dwFlags & MHDR_ISSTRM, "MHDR.dwFlags %lx no ISSTRM when out of queue\n", mhdr.dwFlags); if (!rc2) while(!(mhdr.dwFlags & MHDR_DONE)) { /* Never to be seen except perhaps on multicore */ trace("async MIDI still not done\n"); Sleep(100); } - ok(mhdr.dwFlags & MHDR_DONE, "MHDR.dwFlags %lx not DONE when out of queue\n", mhdr.dwFlags); - test_notification(hwnd, "midiStream callback", MOM_POSITIONCB, (DWORD_PTR)&mhdr); - test_notification(hwnd, "midiStreamOut", MOM_DONE, (DWORD_PTR)&mhdr); + todo_wine_if(swmidi) ok(mhdr.dwFlags & MHDR_DONE, "MHDR.dwFlags %lx not DONE when out of queue\n", mhdr.dwFlags); + test_notification(hwnd, "midiStream callback", MOM_POSITIONCB, (DWORD_PTR)&mhdr, swmidi); + test_notification(hwnd, "midiStreamOut", MOM_DONE, (DWORD_PTR)&mhdr, swmidi);
/* Native fills dwOffset regardless of the cbMidiHdr size argument to midiStreamOut */ - ok(1234567890!=mhdr.dwOffset, "play left MIDIHDR.dwOffset at %lu\n", mhdr.dwOffset); + todo_wine_if(swmidi) ok(1234567890!=mhdr.dwOffset, "play left MIDIHDR.dwOffset at %lu\n", mhdr.dwOffset);
rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare #2 rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare #2 rc=%s\n", mmsys_error(rc));
trace("MIDIHDR stream flags=%lx when finished\n", mhdr.dwFlags); - ok(mhdr.dwFlags & MHDR_DONE, "MHDR.dwFlags when done %lx\n", mhdr.dwFlags); + todo_wine_if(swmidi) ok(mhdr.dwFlags & MHDR_DONE, "MHDR.dwFlags when done %lx\n", mhdr.dwFlags);
test_position(hm, TIME_MS, TIME_MS); test_position(hm, TIME_TICKS, TIME_TICKS); @@ -709,7 +717,7 @@ static void test_midiStream(UINT udev, HWND hwnd) midiprop.tempo.cbStruct = sizeof(midiprop.tempo); rc = midiStreamProperty(hm, (void*)&midiprop, MIDIPROP_GET|MIDIPROP_TEMPO); ok(!rc, "midiStreamProperty TEMPO rc=%s\n", mmsys_error(rc)); - ok(0x0493E0==midiprop.tempo.dwTempo, "stream set tempo %lu\n", midiprop.tdiv.dwTimeDiv); + todo_wine_if(swmidi) ok(0x0493E0==midiprop.tempo.dwTempo, "stream set tempo %lu\n", midiprop.tdiv.dwTimeDiv);
rc = midiStreamRestart(hm); ok(!rc, "midiStreamRestart #2 rc=%s\n", mmsys_error(rc)); @@ -717,9 +725,9 @@ static void test_midiStream(UINT udev, HWND hwnd) mhdr.dwFlags |= MHDR_ISSTRM; /* Preset flags (e.g. MHDR_ISSTRM) do not disturb. */ rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepare used flags %lx rc=%s\n", mhdr.dwFlags, mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepare used flags %lx rc=%s\n", mhdr.dwFlags, mmsys_error(rc)); rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare used flags %lx rc=%s\n", mhdr.dwFlags, mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare used flags %lx rc=%s\n", mhdr.dwFlags, mmsys_error(rc));
rc = midiStreamRestart(hm); ok(!rc, "midiStreamRestart #3 rc=%s\n", mmsys_error(rc)); @@ -738,13 +746,13 @@ static void test_midiStream(UINT udev, HWND hwnd) strmNops[1].dwEvent |= MEVT_F_CALLBACK;
rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepare rc=%s\n", mmsys_error(rc));
rc = playStream(hm, &mhdr); - ok(!rc, "midiStreamOut 0 bytes recorded rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiStreamOut 0 bytes recorded rc=%s\n", mmsys_error(rc));
- test_notification(hwnd, "midiStreamOut", MOM_DONE, (DWORD_PTR)&mhdr); - test_notification(hwnd, "0 bytes recorded", 0, WHATEVER); + test_notification(hwnd, "midiStreamOut", MOM_DONE, (DWORD_PTR)&mhdr, swmidi); + test_notification(hwnd, "0 bytes recorded", 0, WHATEVER, FALSE);
/* FIXME: check dwOffset within callback * instead of the unspecified value afterwards */ @@ -757,34 +765,34 @@ static void test_midiStream(UINT udev, HWND hwnd) mhdr.dwBytesRecorded = 1*sizeof(MIDISHORTEVENT);
rc = playStream(hm, &mhdr); - ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc));
- test_notification(hwnd, "1 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr); - test_notification(hwnd, "1 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr); - test_notification(hwnd, "1 of 2 events", 0, WHATEVER); - ok(0==mhdr.dwOffset, "MIDIHDR.dwOffset 1/2 changed to %lu\n", mhdr.dwOffset); + test_notification(hwnd, "1 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr, swmidi); + test_notification(hwnd, "1 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr, swmidi); + test_notification(hwnd, "1 of 2 events", 0, WHATEVER, FALSE); + todo_wine_if(swmidi) ok(0==mhdr.dwOffset, "MIDIHDR.dwOffset 1/2 changed to %lu\n", mhdr.dwOffset);
mhdr.dwOffset = 1234123123; mhdr.dwBytesRecorded = 2*sizeof(MIDISHORTEVENT);
rc = playStream(hm, &mhdr); - ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc));
- test_notification(hwnd, "2 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr); - test_notification(hwnd, "2 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr); - test_notification(hwnd, "2 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr); - test_notification(hwnd, "2 of 2 events", 0, WHATEVER); - ok(sizeof(MIDISHORTEVENT)==mhdr.dwOffset, "MIDIHDR.dwOffset 2/2 changed to %lu\n", mhdr.dwOffset); + test_notification(hwnd, "2 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr, swmidi); + test_notification(hwnd, "2 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr, swmidi); + test_notification(hwnd, "2 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr, swmidi); + test_notification(hwnd, "2 of 2 events", 0, WHATEVER, FALSE); + todo_wine_if(swmidi) ok(sizeof(MIDISHORTEVENT)==mhdr.dwOffset, "MIDIHDR.dwOffset 2/2 changed to %lu\n", mhdr.dwOffset); ok(mhdr.dwBytesRecorded == 2*sizeof(MIDISHORTEVENT), "dwBytesRecorded changed to %lu\n", mhdr.dwBytesRecorded);
strmNops[0].dwEvent &= ~MEVT_F_CALLBACK; strmNops[1].dwEvent &= ~MEVT_F_CALLBACK; mhdr.dwOffset = 1234123123; rc = playStream(hm, &mhdr); - ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc));
- test_notification(hwnd, "0 CB in 2 events", MOM_DONE, (DWORD_PTR)&mhdr); - test_notification(hwnd, "0 CB in 2 events", 0, WHATEVER); + test_notification(hwnd, "0 CB in 2 events", MOM_DONE, (DWORD_PTR)&mhdr, swmidi); + test_notification(hwnd, "0 CB in 2 events", 0, WHATEVER, FALSE); /* w9X/me/nt set dwOffset to the position played last */ ok(1234123123==mhdr.dwOffset || broken(sizeof(MIDISHORTEVENT)==mhdr.dwOffset), "MIDIHDR.dwOffset nocb changed to %lu\n", mhdr.dwOffset);
@@ -792,20 +800,20 @@ static void test_midiStream(UINT udev, HWND hwnd) rc = playStream(hm, &mhdr); ok(rc==MMSYSERR_INVALPARAM,"midiStreamOut dwBytesRecorded modulo MIDIEVENT rc=%s\n", mmsys_error(rc)); if (!rc) { - test_notification(hwnd, "2 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr); + test_notification(hwnd, "2 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr, FALSE); }
mhdr.dwBytesRecorded = mhdr.dwBufferLength+1; rc = playStream(hm, &mhdr); ok(rc==MMSYSERR_INVALPARAM,"midiStreamOut dwBufferLength<dwBytesRecorded rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "past MIDIHDR tests", 0, WHATEVER); + test_notification(hwnd, "past MIDIHDR tests", 0, WHATEVER, FALSE);
rc = midiStreamStop(hm); ok(!rc, "midiStreamStop rc=%s\n", mmsys_error(rc)); ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %Ix\n", mhdr.dwUser);
rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); ok(0==strmNops[0].dwStreamID, "dwStreamID[0] set to %lx\n", strmNops[0].dwStreamID); ok(0==strmNops[1].dwStreamID, "dwStreamID[1] set to %lx\n", strmNops[1].dwStreamID);
@@ -819,15 +827,15 @@ static void test_midiStream(UINT udev, HWND hwnd) todo_wine ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare stream too large rc=%s\n", mmsys_error(rc));
rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc));
free(mhdr.lpData); }
rc = midiStreamClose(hm); ok(!rc, "midiStreamClose rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiStreamClose", MOM_CLOSE, 0); - test_notification(hwnd, "midiStream over", 0, WHATEVER); + test_notification(hwnd, "midiStreamClose", MOM_CLOSE, 0, FALSE); + test_notification(hwnd, "midiStream over", 0, WHATEVER, FALSE);
rc = midiStreamOpen(&hm, &udev, 1, 0, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION); ok(!rc /*w2k*/|| rc==MMSYSERR_INVALPARAM/*w98*/, "midiStreamOpen NULL function rc=%s\n", mmsys_error(rc)); @@ -860,10 +868,10 @@ static void test_midiStream(UINT udev, HWND hwnd) mhdr.lpData = (LPSTR)strmNopsWithDelta; mhdr.dwBytesRecorded = mhdr.dwBufferLength = sizeof(strmNopsWithDelta); rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepareHeader(dev=%d) rc=%s\n", udev, mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepareHeader(dev=%d) rc=%s\n", udev, mmsys_error(rc));
rc = midiStreamOut(hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiStreamOut(dev=%d) rc=%s\n", udev, mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiStreamOut(dev=%d) rc=%s\n", udev, mmsys_error(rc));
ret = get_position(hm, TIME_MS); ok(ret == expected, "expected %lu, got %lu\n", expected, ret); @@ -904,15 +912,15 @@ static void test_midiStream(UINT udev, HWND hwnd) ok(rc == MMSYSERR_INVALPARAM, "midiStreamProperty(SET|TIMEDIV, dev=%d) rc=%s\n", udev, mmsys_error(rc));
ret = WaitForSingleObject(records.done, 3000); - ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed, got %ld\n", ret); + todo_wine_if(swmidi) ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed, got %ld\n", ret);
rc = midiStreamPause(hm); ok(!rc, "midiStreamPause(dev=%d) rc=%s\n", udev, mmsys_error(rc));
expected = 250; /* = 12 ticks in 120 BPM */ ret = get_position(hm, TIME_MS); - ok(ret >= expected - MARGIN && ret <= expected + MARGIN, - "expected greater than %lums, got %lums\n", expected, ret); + todo_wine_if(swmidi) ok(ret >= expected - MARGIN && ret <= expected + MARGIN, + "expected greater than %lums, got %lums\n", expected, ret); trace("after playing, got %lums\n", ret);
/* set tempo to 240 BPM */ @@ -923,8 +931,8 @@ static void test_midiStream(UINT udev, HWND hwnd)
/* a tempo change doesn't affect elapsed ticks */ ret = get_position(hm, TIME_TICKS); - ok(ret >= strmNopsWithDelta[1].dwDeltaTime && ret < strmNopsWithDelta[1].dwDeltaTime + 3, - "expected %lu ticks, got %lu\n", strmNopsWithDelta[1].dwDeltaTime, ret); + todo_wine_if(swmidi) ok(ret >= strmNopsWithDelta[1].dwDeltaTime && ret < strmNopsWithDelta[1].dwDeltaTime + 3, + "expected %lu ticks, got %lu\n", strmNopsWithDelta[1].dwDeltaTime, ret);
midiprop.tdiv.cbStruct = sizeof(midiprop.tdiv); rc = midiStreamProperty(hm, (void*)&midiprop, MIDIPROP_GET | MIDIPROP_TIMEDIV); @@ -936,17 +944,17 @@ static void test_midiStream(UINT udev, HWND hwnd) ret = get_position(hm, TIME_MIDI); ok(ret == expected, "expected song pointer %lu, got %lu\n", expected, ret);
- ok(records.count == 2, "expected 2 MM_MOM_DONE messages, got %d\n", records.count); + todo_wine_if(swmidi) ok(records.count == 2, "expected 2 MM_MOM_DONE messages, got %d\n", records.count);
/* Time between midiStreamPause and midiStreamRestart isn't counted. So, the second event happens at dwDeltaTime(250ms) + 100ms after the first event. */ expected = 250 + 100; diff = records.time_stamp[1] - records.time_stamp[0]; - ok(diff >= expected - MARGIN && diff <= expected + MARGIN, - "expected %lu ~ %lums, got %lums (dev=%d)\n", expected - MARGIN, expected + MARGIN, diff, udev); + todo_wine_if(swmidi) ok(diff >= expected - MARGIN && diff <= expected + MARGIN, + "expected %lu ~ %lums, got %lums (dev=%d)\n", expected - MARGIN, expected + MARGIN, diff, udev);
rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepareHeader(dev=%d) rc=%s\n", udev, mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepareHeader(dev=%d) rc=%s\n", udev, mmsys_error(rc));
rc = midiStreamStop(hm); ok(!rc, "midiStreamStop(dev=%d) rc=%s\n", udev, mmsys_error(rc)); @@ -986,7 +994,7 @@ static void test_midiStream(UINT udev, HWND hwnd) else rc = midiStreamOpen(&hm, &udev, 1, (DWORD_PTR)callback_func, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION); ok(!rc, "midiOutOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc)); - test_notification(hwnd, "midiStreamOpen", MOM_OPEN, 0); + test_notification(hwnd, "midiStreamOpen", MOM_OPEN, 0, FALSE);
midiprop.tdiv.cbStruct = sizeof(midiprop.tdiv); midiprop.tdiv.dwTimeDiv = 480; @@ -1033,20 +1041,20 @@ static void test_midiStream(UINT udev, HWND hwnd) #undef ROUNDUP4
rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutPrepareHeader rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutPrepareHeader rc=%s\n", mmsys_error(rc));
rc = playStream(hm, &mhdr); - ok(!rc, "midiStreamOut rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiStreamOut", MOM_DONE, (DWORD_PTR)&mhdr); + todo_wine_if(swmidi) ok(!rc, "midiStreamOut rc=%s\n", mmsys_error(rc)); + test_notification(hwnd, "midiStreamOut", MOM_DONE, (DWORD_PTR)&mhdr, swmidi);
rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); - ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); + todo_wine_if(swmidi) ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc));
free(mhdr.lpData); } rc = midiStreamClose(hm); ok(!rc, "midiOutClose rc=%s\n", mmsys_error(rc)); - test_notification(hwnd, "midiStreamClose", MOM_CLOSE, 0); + test_notification(hwnd, "midiStreamClose", MOM_CLOSE, 0, FALSE); }
static BOOL scan_subkeys(HKEY parent, const LPCSTR *sub_keys)
From: Anton Baskanov baskanov@gmail.com
--- dlls/wineswmidi/Makefile.in | 1 + dlls/wineswmidi/swmidi.c | 118 ++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+)
diff --git a/dlls/wineswmidi/Makefile.in b/dlls/wineswmidi/Makefile.in index 5e9a8995868..24210437d0a 100644 --- a/dlls/wineswmidi/Makefile.in +++ b/dlls/wineswmidi/Makefile.in @@ -1,4 +1,5 @@ MODULE = wineswmidi.dll +IMPORTS = uuid ole32 DELAYIMPORTS = winmm
SOURCES = \ diff --git a/dlls/wineswmidi/swmidi.c b/dlls/wineswmidi/swmidi.c index f203ad1221a..4e8f50786ff 100644 --- a/dlls/wineswmidi/swmidi.c +++ b/dlls/wineswmidi/swmidi.c @@ -24,10 +24,16 @@ #include "mmddk.h" #include "mmdeviceapi.h"
+#include "initguid.h" +#include "dmusicc.h" + #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(midi);
+#define SWMIDI_AUDIO_CHANNELS 2 +#define SWMIDI_SAMPLE_RATE 22050 + struct swmidi { CRITICAL_SECTION cs; @@ -35,10 +41,93 @@ struct swmidi BOOL open; MIDIOPENDESC open_desc; WORD flags; + + HANDLE close_event; + HANDLE open_event; + HANDLE thread; + DWORD init_result; + + IDirectMusic *dmusic; + IDirectMusicPort *port; };
static struct swmidi swmidi;
+static HRESULT init_dmusic(void) +{ + DMUS_PORTPARAMS port_params; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, + (void **)&swmidi.dmusic); + if (FAILED(hr)) + return hr; + + hr = IDirectMusic_SetDirectSound(swmidi.dmusic, NULL, NULL); + if (FAILED(hr)) + { + IDirectMusic_Release(swmidi.dmusic); + return hr; + } + + memset(&port_params, 0, sizeof(port_params)); + port_params.dwSize = sizeof(port_params); + port_params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS + | DMUS_PORTPARAMS_SAMPLERATE | DMUS_PORTPARAMS_EFFECTS; + port_params.dwChannelGroups = 1; + port_params.dwAudioChannels = SWMIDI_AUDIO_CHANNELS; + port_params.dwSampleRate = SWMIDI_SAMPLE_RATE; + port_params.dwEffectFlags = 0; + hr = IDirectMusic_CreatePort(swmidi.dmusic, &GUID_NULL, &port_params, &swmidi.port, NULL); + if (FAILED(hr)) + { + IDirectMusic_Release(swmidi.dmusic); + return hr; + } + + if (FAILED(IDirectMusicPort_Activate(swmidi.port, TRUE))) + { + IDirectMusicPort_Release(swmidi.port); + IDirectMusic_Release(swmidi.dmusic); + return hr; + } + + return S_OK; +} + +static void destroy_dmusic(void) +{ + IDirectMusicPort_Activate(swmidi.port, FALSE); + IDirectMusicPort_Release(swmidi.port); + IDirectMusic_Release(swmidi.dmusic); +} + +static DWORD WINAPI thread_proc(void *param) +{ + SetThreadDescription(GetCurrentThread(), L"swmidi"); + + CoInitialize(NULL); + + if (FAILED(init_dmusic())) + { + CoUninitialize(); + swmidi.init_result = MMSYSERR_ERROR; + SetEvent(swmidi.open_event); + return 0; + } + + swmidi.init_result = MMSYSERR_NOERROR; + SetEvent(swmidi.open_event); + + WaitForSingleObject(swmidi.close_event, INFINITE); + + destroy_dmusic(); + + CoUninitialize(); + + return 0; +} + static DWORD swmidi_init(void) { TRACE("\n"); @@ -88,6 +177,28 @@ static DWORD swmidi_open(MIDIOPENDESC *desc, UINT flags) return MMSYSERR_ALLOCATED; }
+ swmidi.close_event = CreateEventA(NULL, FALSE, FALSE, NULL); + swmidi.open_event = CreateEventA(NULL, FALSE, FALSE, NULL); + + swmidi.thread = CreateThread(NULL, 0, thread_proc, NULL, 0, NULL); + if (!swmidi.thread) + { + LeaveCriticalSection(&swmidi.cs); + return MMSYSERR_ERROR; + } + + WaitForSingleObject(swmidi.open_event, INFINITE); + + if (swmidi.init_result != MMSYSERR_NOERROR) + { + WaitForSingleObject(swmidi.thread, INFINITE); + CloseHandle(swmidi.thread); + CloseHandle(swmidi.open_event); + CloseHandle(swmidi.close_event); + LeaveCriticalSection(&swmidi.cs); + return swmidi.init_result; + } + swmidi.open = TRUE; swmidi.open_desc = *desc; swmidi.flags = HIWORD(flags & CALLBACK_TYPEMASK); @@ -106,6 +217,13 @@ static DWORD swmidi_close(void)
EnterCriticalSection(&swmidi.cs);
+ SetEvent(swmidi.close_event); + WaitForSingleObject(swmidi.thread, INFINITE); + + CloseHandle(swmidi.thread); + CloseHandle(swmidi.open_event); + CloseHandle(swmidi.close_event); + swmidi.open = FALSE;
LeaveCriticalSection(&swmidi.cs);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=151180
Your paranoid android.
=== debian11b (64 bit WoW report) ===
kernel32: comm.c:1586: Test failed: Unexpected time 1001, expected around 500
user32: input.c:4306: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000000D600EC, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032 msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got hook 0x0009 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got hook 0x0005 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got winevent_hook 0x0003 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got msg 0x030f instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got msg 0x001c instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got msg 0x0086 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got msg 0x0006 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got hook 0x0009 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got winevent_hook 0x8005 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got msg 0x0007 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got msg 0x0008 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got winevent_hook 0x8005 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got msg 0x0007 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 3: the msg 0x00f3 was expected, but got msg 0x0138 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 5: the winevent_hook 0x800a was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 6: the msg 0x0202 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 7: the msg 0x00f3 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 8: the msg 0x0138 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 9: the winevent_hook 0x800a was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 10: the msg 0x0087 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 11: the msg 0x00f1 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 12: the msg 0x0087 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 13: the msg 0x00f1 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 14: the msg 0x0138 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 15: the winevent_hook 0x800a was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 16: the msg 0x0087 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 17: the msg 0x00f1 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 18: the msg 0x0138 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 19: the winevent_hook 0x800a was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 20: the msg 0x0087 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 21: the winevent_hook 0x0009 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 22: the msg 0x0215 was expected, but got msg 0x0111 instead msg.c:7536: Test failed: BM_CLICK on auto-radio button: 23: in msg 0x0111 expecting wParam 0x1f6 got 0x601f6 msg.c:7536: Test failed: BM_CLICK on auto-radio button: 27: the msg sequence is not complete: expected msg 0000 - actual msg 00f3
v2: - Fix test failures.