#include <mmddk.h>
#include <mmebuddy.h>
+#include <ks.h>
+#include <ksmedia.h>
+#include "interface.h"
+
#define KERNEL_DEVICE_NAME L"\\\\Device\\wdmaud"
+PWSTR UnknownWaveIn = L"Wave Input";
+PWSTR UnknownWaveOut = L"Wave Output";
+PWSTR UnknownMidiIn = L"Midi Input";
+PWSTR UnknownMidiOut = L"Midi Output";
+
HANDLE KernelHandle = INVALID_HANDLE_VALUE;
+DWORD OpenCount = 0;
+
+
+MMRESULT
+GetNumWdmDevs(
+ IN HANDLE Handle,
+ IN MMDEVICE_TYPE DeviceType,
+ OUT DWORD* DeviceCount)
+{
+ MMRESULT Result;
+ WDMAUD_DEVICE_INFO DeviceInfo;
+
+ VALIDATE_MMSYS_PARAMETER( Handle != INVALID_HANDLE_VALUE );
+ VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
+ VALIDATE_MMSYS_PARAMETER( DeviceCount );
+
+ ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+ DeviceInfo.DeviceType = DeviceType;
+
+ Result = SyncOverlappedDeviceIoControl(Handle,
+ IOCTL_GETNUMDEVS_TYPE,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+
+ if ( ! Result )
+ {
+ *DeviceCount = 0;
+ return TranslateInternalMmResult(Result);
+ }
+
+ *DeviceCount = DeviceInfo.DeviceCount;
+
+ return MMSYSERR_NOERROR;
+}
+
+MMRESULT
+GetWdmDeviceCapabilities(
+ IN PSOUND_DEVICE SoundDevice,
+ OUT PVOID Capabilities,
+ IN DWORD CapabilitiesSize)
+{
+ /* NOTE - At this time, WDMAUD does not support this properly */
+
+ MMRESULT Result;
+ MMDEVICE_TYPE DeviceType;
+
+ SND_ASSERT( SoundDevice );
+ SND_ASSERT( Capabilities );
+
+ SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities\n");
+
+ Result = GetSoundDeviceType(SoundDevice, &DeviceType);
+ SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+ if ( ! MMSUCCESS(Result) )
+ return Result;
+
+ /* This is pretty much a big hack right now */
+ switch ( DeviceType )
+ {
+ case WAVE_OUT_DEVICE_TYPE :
+ {
+ LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities;
+ WaveOutCaps->wMid = 0;
+ WaveOutCaps->wPid = 0;
+ WaveOutCaps->vDriverVersion = 0x0001;
+ CopyWideString(WaveOutCaps->szPname, UnknownWaveOut);
+
+ /* HACK: We may not really support all formats! */
+ WaveOutCaps->dwFormats = 0xffffffff;
+ WaveOutCaps->wChannels = 2;
+ WaveOutCaps->dwSupport = 0;
+ break;
+ }
+ case WAVE_IN_DEVICE_TYPE :
+ {
+ LPWAVEINCAPS WaveInCaps = (LPWAVEINCAPS) Capabilities;
+ CopyWideString(WaveInCaps->szPname, UnknownWaveIn);
+ /* TODO... other fields */
+ break;
+ }
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+
+MMRESULT
+OpenWdmSoundDevice(
+ IN struct _SOUND_DEVICE* SoundDevice, /* NOT USED */
+ OUT PVOID* Handle)
+{
+ /* Only open this if it's not already open */
+ if ( KernelHandle == INVALID_HANDLE_VALUE )
+ {
+ KernelHandle = CreateFile(KERNEL_DEVICE_NAME,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL);
+ }
+
+ if ( KernelHandle == INVALID_HANDLE_VALUE )
+ return MMSYSERR_ERROR;
+
+ SND_ASSERT( Handle );
+
+ *Handle = KernelHandle;
+ ++ OpenCount;
+
+ return MMSYSERR_NOERROR;
+}
+
+MMRESULT
+CloseWdmSoundDevice(
+ IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, /* NOT USED */
+ IN PVOID Handle)
+{
+ SND_ASSERT( OpenCount > 0 );
+ SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE );
+
+ -- OpenCount;
+
+ if ( OpenCount < 1 )
+ {
+ CloseHandle(KernelHandle);
+ KernelHandle = INVALID_HANDLE_VALUE;
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+
+MMRESULT
+QueryWdmWaveDeviceFormatSupport(
+ IN PSOUND_DEVICE Device,
+ IN PWAVEFORMATEX WaveFormat,
+ IN DWORD WaveFormatSize)
+{
+ /* Whatever... */
+ return MMSYSERR_NOERROR;
+}
+
+MMRESULT
+SetWdmWaveDeviceFormat(
+ IN PSOUND_DEVICE_INSTANCE Instance,
+ IN PWAVEFORMATEX WaveFormat,
+ IN DWORD WaveFormatSize)
+{
+ MMRESULT Result;
+ PSOUND_DEVICE SoundDevice;
+ PVOID Identifier;
+ WDMAUD_DEVICE_INFO DeviceInfo;
+
+ Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
+
+ if ( ! MMSUCCESS(Result) )
+ {
+ return TranslateInternalMmResult(Result);
+ }
+
+ Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier);
+
+ if ( ! MMSUCCESS(Result) )
+ {
+ return TranslateInternalMmResult(Result);
+ }
+
+ ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+ DeviceInfo.u.WaveFormatEx.cbSize = WaveFormat->cbSize;
+ DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
+ DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels;
+ DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
+ DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
+ DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
+ DeviceInfo.u.WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
+
+ Result = SyncOverlappedDeviceIoControl(KernelHandle,
+ IOCTL_OPEN_WDMAUD,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+
+ if ( ! MMSUCCESS(Result) )
+ {
+ return TranslateInternalMmResult(Result);
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+
+MMRESULT
+PopulateWdmDeviceList(
+ HANDLE Handle,
+ MMDEVICE_TYPE DeviceType)
+{
+ MMRESULT Result;
+ DWORD DeviceCount = 0;
+ PSOUND_DEVICE SoundDevice = NULL;
+ MMFUNCTION_TABLE FuncTable;
+ DWORD i;
+
+ VALIDATE_MMSYS_PARAMETER( Handle != INVALID_HANDLE_VALUE );
+ VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
+
+ Result = GetNumWdmDevs(Handle, 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, (PVOID) 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 = GetWdmDeviceCapabilities;
+ FuncTable.QueryWaveFormatSupport = QueryWdmWaveDeviceFormatSupport;
+ FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
+ FuncTable.Open = OpenWdmSoundDevice;
+ FuncTable.Close = CloseWdmSoundDevice;
+ //FuncTable.CommitWaveBuffer = WriteFileEx_Committer;
+
+ SetSoundDeviceFunctionTable(SoundDevice, &FuncTable);
+ }
+
+ return MMSYSERR_NOERROR;
+}
+
+
APIENTRY LONG
DriverProc(
{
case DRV_LOAD :
{
+ HANDLE Handle;
SND_TRACE(L"DRV_LOAD\n");
Result = InitEntrypointMutexes();
if ( ! MMSUCCESS(Result) )
return 0L;
- KernelHandle = CreateFile(KERNEL_DEVICE_NAME,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_WRITE, // ok?
- NULL,
- OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED,
- NULL);
+ OpenWdmSoundDevice(NULL, &Handle);
- if ( KernelHandle == INVALID_HANDLE_VALUE )
+ if ( Handle == INVALID_HANDLE_VALUE )
{
SND_ERR(L"Failed to open %s\n", KERNEL_DEVICE_NAME);
CleanupEntrypointMutexes();
- UnlistAllSoundDevices();
+ //UnlistAllSoundDevices();
return 0L;
}
+ /* Populate the device lists */
+ SND_TRACE(L"Populating device lists\n");
+ PopulateWdmDeviceList(KernelHandle, WAVE_OUT_DEVICE_TYPE);
+ PopulateWdmDeviceList(KernelHandle, WAVE_IN_DEVICE_TYPE);
+ PopulateWdmDeviceList(KernelHandle, MIDI_OUT_DEVICE_TYPE);
+ PopulateWdmDeviceList(KernelHandle, MIDI_IN_DEVICE_TYPE);
+ PopulateWdmDeviceList(KernelHandle, AUX_DEVICE_TYPE);
+ PopulateWdmDeviceList(KernelHandle, MIXER_DEVICE_TYPE);
+
+ CloseWdmSoundDevice(NULL, Handle);
+
SND_TRACE(L"Initialisation complete\n");
return 1L;