reactos/dll/win32/wdmaud.drv/wdmaud.c
Joachim Henze 57516edb42 [WDMAUD.DRV] Improve AC97 driver from rapps by defining USE_MMIXER_LIB
By taking alternative code-paths in WdmAud and bypassing Sysaudio.
This is my 2nd attempt to commit that.

Using USE_MMIXER_LIB relies on those 2 previous patches:
0.4.15-dev-765-g b8e936a57b CORE17214 (#3148) wdmaud-racecondition-fix and
0.4.15-dev-796-g a27f0debca CORE17276 winmm:mixer-testbot-crash-fix

Defining USE_MMIXER_LIB will fix/improve:
- the test execution times of "GCCLin_x86 on Test VBox" will be dramatically improve (iirc by ~10-15min)
- CORE-8726/CORE-9986/CORE-16564 AC97 driver from rapps will work in the same session that the driver is installed, not a single reboot is needed anymore
- CORE13202 Unhandled exception from wdmaud.drv when recording sound in Scratch 1.4 leads to app-crash (gets fixed even for older builds that did not receive 0.4.15-dev-2794-g 81f8bce yet)
- CORE-13488 A deadlock in "DiabloII" character selection screen and "The Lion King II"
- CORE-9981 "DosBox + Commander Keen6" almost 100% fixed, DosBox + Commander Keen6 properly plays music instead of garbled output,
            same improvement for "ScummVM 2.0 with Monkey Island 2"

The playback is not yet *entirely* perfect, still a few hiccups now and then, but by orders of magnitude better than before.

Defining USE_MMIXER_LIB will also have some negative aspects:
- CORE-17277 crash of dsound:duplex on "GCCLin_x86 on Test VBox" gets unhidden on the bot, but was proven to be broken even beforehand already. The driver beforehand was just not found and the tests were skipped therefore.
- CORE-17278 crash of dsound:capture on "GCCLin_x86 on Test VBox" gets unhidden on the bot, but was proven to be broken even beforehand already. The driver beforehand was just not found and the tests were skipped therefore.
- It may also have a negative impact for CORE-17285 "Realtek HD Audio" but Oleg Dubinsky accepted to tolerate that and aims to approach it differently. I will resolve that as WontFix now.
2021-08-30 19:52:30 +02:00

230 lines
6.2 KiB
C

/*
* PROJECT: ReactOS Sound System
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll/win32/wdmaud.drv/wdmaud.c
*
* PURPOSE: WDM Audio Driver (User-mode part)
* PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
*
* NOTES: Looking for wodMessage & co? You won't find them here. Try
* the MME Buddy library, which is where these routines are
* actually implemented.
*
*/
#include "wdmaud.h"
#define NDEBUG
#include <debug.h>
#include <mmebuddy_debug.h>
#define USE_MMIXER_LIB
#ifndef USE_MMIXER_LIB
#define FUNC_NAME(x) x##ByLegacy
#else
#define FUNC_NAME(x) x##ByMMixer
#endif
MMRESULT
QueryWdmWaveDeviceFormatSupport(
IN PSOUND_DEVICE Device,
IN PWAVEFORMATEX WaveFormat,
IN DWORD WaveFormatSize)
{
/* Whatever... */
return MMSYSERR_NOERROR;
}
MMRESULT
PopulateWdmDeviceList(
MMDEVICE_TYPE DeviceType)
{
MMRESULT Result;
DWORD DeviceCount = 0;
PSOUND_DEVICE SoundDevice = NULL;
MMFUNCTION_TABLE FuncTable;
DWORD i;
VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
Result = FUNC_NAME(WdmAudGetNumWdmDevs)(DeviceType, &DeviceCount);
if ( ! MMSUCCESS(Result) )
{
SND_ERR(L"Error %d while obtaining number of devices\n", Result);
return TranslateInternalMmResult(Result);
}
SND_TRACE(L"%d devices of type %d found\n", DeviceCount, DeviceType);
for ( i = 0; i < DeviceCount; ++ i )
{
Result = ListSoundDevice(DeviceType, UlongToPtr(i), &SoundDevice);
if ( ! MMSUCCESS(Result) )
{
SND_ERR(L"Failed to list sound device - error %d\n", Result);
return TranslateInternalMmResult(Result);
}
/* Set up our function table */
ZeroMemory(&FuncTable, sizeof(MMFUNCTION_TABLE));
FuncTable.GetCapabilities = FUNC_NAME(WdmAudGetCapabilities);
FuncTable.QueryWaveFormatSupport = QueryWdmWaveDeviceFormatSupport; //FIXME
FuncTable.Open = FUNC_NAME(WdmAudOpenSoundDevice);
FuncTable.Close = FUNC_NAME(WdmAudCloseSoundDevice);
FuncTable.GetDeviceInterfaceString = FUNC_NAME(WdmAudGetDeviceInterfaceString);
if (DeviceType == MIXER_DEVICE_TYPE)
{
FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetMixerDeviceFormat);
FuncTable.QueryMixerInfo = FUNC_NAME(WdmAudQueryMixerInfo);
}
else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
{
FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetWaveDeviceFormat);
FuncTable.SetState = FUNC_NAME(WdmAudSetWaveState);
FuncTable.ResetStream = FUNC_NAME(WdmAudResetStream);
FuncTable.GetPos = FUNC_NAME(WdmAudGetWavePosition);
#ifndef USERMODE_MIXER
FuncTable.CommitWaveBuffer = FUNC_NAME(WdmAudCommitWaveBuffer);
#else
FuncTable.CommitWaveBuffer = WriteFileEx_Remixer;
#endif
}
else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE)
{
FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetMixerDeviceFormat);
FuncTable.SetState = FUNC_NAME(WdmAudSetWaveState);
FuncTable.GetPos = FUNC_NAME(WdmAudGetWavePosition);
}
SetSoundDeviceFunctionTable(SoundDevice, &FuncTable);
}
return MMSYSERR_NOERROR;
}
LONG
APIENTRY
DriverProc(
DWORD DriverId,
HANDLE DriverHandle,
UINT Message,
LONG Parameter1,
LONG Parameter2)
{
switch ( Message )
{
case DRV_LOAD :
{
HANDLE Handle;
MMRESULT Result;
SND_TRACE(L"DRV_LOAD\n");
Result = InitEntrypointMutexes();
if ( ! MMSUCCESS(Result) )
return 0L;
Result = FUNC_NAME(WdmAudOpenSoundDevice)(NULL, &Handle);
if ( Result != MMSYSERR_NOERROR )
{
SND_ERR(L"Failed to open \\\\.\\wdmaud\n");
//UnlistAllSoundDevices();
return 0L;
}
/* Populate the device lists */
SND_TRACE(L"Populating device lists\n");
PopulateWdmDeviceList(WAVE_OUT_DEVICE_TYPE);
PopulateWdmDeviceList(WAVE_IN_DEVICE_TYPE);
PopulateWdmDeviceList(MIDI_OUT_DEVICE_TYPE);
PopulateWdmDeviceList(MIDI_IN_DEVICE_TYPE);
PopulateWdmDeviceList(AUX_DEVICE_TYPE);
PopulateWdmDeviceList(MIXER_DEVICE_TYPE);
SND_TRACE(L"Initialisation complete\n");
return 1L;
}
case DRV_FREE :
{
SND_TRACE(L"DRV_FREE\n");
FUNC_NAME(WdmAudCleanup)();
/* TODO: Clean up the path names! */
UnlistAllSoundDevices();
CleanupEntrypointMutexes();
SND_TRACE(L"Unfreed memory blocks: %d\n",
GetMemoryAllocationCount());
return 1L;
}
case DRV_ENABLE :
case DRV_DISABLE :
{
SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n");
return 1L;
}
case DRV_OPEN :
case DRV_CLOSE :
{
SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n");
return 1L;
}
case DRV_QUERYCONFIGURE :
{
SND_TRACE(L"DRV_QUERYCONFIGURE\n");
return 0L;
}
case DRV_CONFIGURE :
return DRVCNF_OK;
default :
SND_TRACE(L"Unhandled message %d\n", Message);
return DefDriverProc(DriverId,
DriverHandle,
Message,
Parameter1,
Parameter2);
}
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
switch ( fdwReason )
{
case DLL_PROCESS_ATTACH :
SND_TRACE(L"WDMAUD.DRV - Process attached\n");
break;
case DLL_PROCESS_DETACH :
SND_TRACE(L"WDMAUD.DRV - Process detached\n");
break;
case DLL_THREAD_ATTACH :
SND_TRACE(L"WDMAUD.DRV - Thread attached\n");
break;
case DLL_THREAD_DETACH :
SND_TRACE(L"WDMAUD.DRV - Thread detached\n");
break;
}
return TRUE;
}