winmm/tests: Demonstrate that WOM_DONE is not invoked reentrantly.

Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Liam Murphy 2022-01-27 10:22:59 -06:00 committed by Alexandre Julliard
parent e385df7d2e
commit bf65b96b01
1 changed files with 103 additions and 0 deletions

View File

@ -1626,6 +1626,108 @@ static void test_fragmentsize(void)
CloseHandle(hevent); CloseHandle(hevent);
} }
static void CALLBACK test_reentrant_callback_func(HWAVEOUT hwo, UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
static int wom_done_count = 0;
switch(uMsg){
case WOM_OPEN:
case WOM_CLOSE:
ok(GetCurrentThreadId() == g_tid, "Got different thread ID\n");
break;
case WOM_DONE:
/* verify that WOM_DONE is not sent during the following waveOutWrite */
todo_wine_if(wom_done_count == 1)
ok(g_tid == 0, "callback called reentrantly\n");
g_tid = GetCurrentThreadId();
if(wom_done_count++ == 0){
Sleep(125); /* ensure 2nd header is done playing before waveOutWrite */
waveOutWrite(hwo, (WAVEHDR *)dwParam1, sizeof(WAVEHDR));
}
break;
}
g_tid = 0;
SetEvent((HANDLE)dwInstance);
}
static void test_reentrant_callback(void)
{
MMRESULT rc;
WAVEHDR hdr[2];
HWAVEOUT wout;
WAVEFORMATEX fmt;
DWORD wait;
HANDLE hevent;
if(waveOutGetNumDevs() == 0)
return;
fmt.wFormatTag = WAVE_FORMAT_PCM;
fmt.nChannels = 2;
fmt.nSamplesPerSec = 44100;
fmt.wBitsPerSample = 16;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec;
fmt.cbSize = sizeof(WAVEFORMATEX);
hevent = CreateEventW(NULL, FALSE, FALSE, NULL);
g_tid = GetCurrentThreadId();
rc = waveOutOpen(&wout, WAVE_MAPPER, &fmt, (DWORD_PTR)test_reentrant_callback_func,
(DWORD_PTR)hevent, CALLBACK_FUNCTION);
ok(rc == MMSYSERR_NOERROR || rc == WAVERR_BADFORMAT ||
rc == MMSYSERR_INVALFLAG || rc == MMSYSERR_INVALPARAM,
"waveOutOpen(%s) failed: %s\n", dev_name(WAVE_MAPPER), wave_out_error(rc));
if(rc != MMSYSERR_NOERROR){
CloseHandle(hevent);
return;
}
wait = WaitForSingleObject(hevent, 1000);
ok(wait == WAIT_OBJECT_0, "wave open callback missed\n");
memset(hdr, 0, sizeof(hdr));
hdr[0].dwBufferLength = (fmt.nSamplesPerSec * fmt.nBlockAlign / 10);
hdr[1].dwBufferLength = hdr[0].dwBufferLength;
hdr[1].lpData = hdr[0].lpData =
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, hdr[0].dwBufferLength);
rc = waveOutPrepareHeader(wout, &hdr[0], sizeof(hdr[0]));
ok(rc == MMSYSERR_NOERROR, "waveOutPrepareHeader failed: %s\n", wave_out_error(rc));
rc = waveOutPrepareHeader(wout, &hdr[1], sizeof(hdr[1]));
ok(rc == MMSYSERR_NOERROR, "waveOutPrepareHeader failed: %s\n", wave_out_error(rc));
rc = waveOutWrite(wout, &hdr[0], sizeof(hdr[0]));
ok(rc == MMSYSERR_NOERROR, "waveOutWrite failed: %s\n", wave_out_error(rc));
rc = waveOutWrite(wout, &hdr[1], sizeof(hdr[1]));
ok(rc == MMSYSERR_NOERROR, "waveOutWrite failed: %s\n", wave_out_error(rc));
wait = WaitForSingleObject(hevent, 1000);
ok(wait == WAIT_OBJECT_0, "header 1 callback missed\n");
wait = WaitForSingleObject(hevent, 1000);
ok(wait == WAIT_OBJECT_0, "header 2 callback missed\n");
wait = WaitForSingleObject(hevent, 1000);
ok(wait == WAIT_OBJECT_0, "header 3 callback missed\n");
g_tid = GetCurrentThreadId();
rc = waveOutClose(wout);
ok(rc == MMSYSERR_NOERROR, "waveOutClose failed: %s\n", wave_out_error(rc));
HeapFree(GetProcessHeap(), 0, hdr[0].lpData);
CloseHandle(hevent);
}
static void create_wav_file(char *temp_file) static void create_wav_file(char *temp_file)
{ {
WAVEFORMATEX format; WAVEFORMATEX format;
@ -1727,5 +1829,6 @@ START_TEST(wave)
wave_out_tests(); wave_out_tests();
test_sndPlaySound(); test_sndPlaySound();
test_fragmentsize(); test_fragmentsize();
test_reentrant_callback();
test_PlaySound(); test_PlaySound();
} }