From 98826b3fe1690fb88873b669cba428bfe06679f6 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sun, 13 Dec 2009 15:36:19 +0000 Subject: [PATCH] [WDMAUD.DRV] - Integrate mmixer library into wdmaud.drv - Library is not yet used svn path=/trunk/; revision=44562 --- reactos/dll/win32/wdmaud.drv/mmixer.c | 329 +++++++++++++++++++++ reactos/dll/win32/wdmaud.drv/wdmaud.c | 67 ++++- reactos/dll/win32/wdmaud.drv/wdmaud.h | 63 ++++ reactos/dll/win32/wdmaud.drv/wdmaud.rbuild | 4 + 4 files changed, 451 insertions(+), 12 deletions(-) create mode 100644 reactos/dll/win32/wdmaud.drv/mmixer.c create mode 100644 reactos/dll/win32/wdmaud.drv/wdmaud.h diff --git a/reactos/dll/win32/wdmaud.drv/mmixer.c b/reactos/dll/win32/wdmaud.drv/mmixer.c new file mode 100644 index 00000000000..3f5fa1b1e6a --- /dev/null +++ b/reactos/dll/win32/wdmaud.drv/mmixer.c @@ -0,0 +1,329 @@ +/* + * PROJECT: ReactOS Sound System + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/wdmaud.drv/mmixer.c + * + * PURPOSE: WDM Audio Mixer API (User-mode part) + * PROGRAMMERS: Johannes Anderwald + */ + +#include "wdmaud.h" + + +PVOID Alloc(ULONG NumBytes); +MIXER_STATUS Close(HANDLE hDevice); +VOID Free(PVOID Block); +VOID Copy(PVOID Src, PVOID Dst, ULONG NumBytes); +MIXER_STATUS Open(IN LPWSTR DevicePath, OUT PHANDLE hDevice); +MIXER_STATUS Control(IN HANDLE hMixer, IN ULONG dwIoControlCode, IN PVOID lpInBuffer, IN ULONG nInBufferSize, OUT PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned); +MIXER_STATUS Enum(IN PVOID EnumContext, IN ULONG DeviceIndex, OUT LPWSTR * DeviceName, OUT PHANDLE OutHandle); + +MIXER_CONTEXT MixerContext = +{ + sizeof(MIXER_CONTEXT), + NULL, + Alloc, + Control, + Free, + Open, + Close, + Copy +}; + +GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO}; + +PVOID Alloc(ULONG NumBytes) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumBytes); +} + +MIXER_STATUS +Close(HANDLE hDevice) +{ + if (CloseHandle(hDevice)) + return MM_STATUS_SUCCESS; + else + return MM_STATUS_UNSUCCESSFUL; +} + +VOID +Free(PVOID Block) +{ + HeapFree(GetProcessHeap(), 0, Block); +} + +VOID +Copy(PVOID Src, PVOID Dst, ULONG NumBytes) +{ + CopyMemory(Src, Dst, NumBytes); +} + +MIXER_STATUS +Open( + IN LPWSTR DevicePath, + OUT PHANDLE hDevice) +{ + DevicePath[1] = L'\\'; + *hDevice = CreateFileW(DevicePath, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + if (*hDevice == INVALID_HANDLE_VALUE) + { + return MM_STATUS_UNSUCCESSFUL; + } + + return MM_STATUS_SUCCESS; +} + +MIXER_STATUS +Control( + IN HANDLE hMixer, + IN ULONG dwIoControlCode, + IN PVOID lpInBuffer, + IN ULONG nInBufferSize, + OUT PVOID lpOutBuffer, + ULONG nOutBufferSize, + PULONG lpBytesReturned) +{ + OVERLAPPED Overlapped; + BOOLEAN IoResult; + DWORD Transferred = 0; + + /* Overlapped I/O is done here - this is used for waiting for completion */ + ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); + Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if ( ! Overlapped.hEvent ) + return MM_STATUS_NO_MEMORY; + + /* Talk to the device */ + IoResult = DeviceIoControl(hMixer, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, + &Transferred, + &Overlapped); + + /* If failure occurs, make sure it's not just due to the overlapped I/O */ + if ( ! IoResult ) + { + if ( GetLastError() != ERROR_IO_PENDING ) + { + CloseHandle(Overlapped.hEvent); + + if (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + if ( lpBytesReturned ) + *lpBytesReturned = Transferred; + return MM_STATUS_MORE_ENTRIES; + } + + return MM_STATUS_UNSUCCESSFUL; + } + } + + /* Wait for the I/O to complete */ + IoResult = GetOverlappedResult(hMixer, + &Overlapped, + &Transferred, + TRUE); + + /* Don't need this any more */ + CloseHandle(Overlapped.hEvent); + + if ( ! IoResult ) + return MM_STATUS_UNSUCCESSFUL; + + if ( lpBytesReturned ) + *lpBytesReturned = Transferred; + + return MM_STATUS_SUCCESS; +} + +MIXER_STATUS +Enum( + IN PVOID EnumContext, + IN ULONG DeviceIndex, + OUT LPWSTR * DeviceName, + OUT PHANDLE OutHandle) +{ + SP_DEVICE_INTERFACE_DATA InterfaceData; + SP_DEVINFO_DATA DeviceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData; + BOOL Result; + DWORD Length; + + //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle); + + InterfaceData.cbSize = sizeof(InterfaceData); + InterfaceData.Reserved = 0; + + Result = SetupDiEnumDeviceInterfaces(EnumContext, + NULL, + &CategoryGuid, + DeviceIndex, + &InterfaceData); + + if (!Result) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + { + return MM_STATUS_NO_MORE_DEVICES; + } + return MM_STATUS_UNSUCCESSFUL; + } + + Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR); + DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), + 0, + Length); + DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); + DeviceData.cbSize = sizeof(DeviceData); + DeviceData.Reserved = 0; + + Result = SetupDiGetDeviceInterfaceDetailW(EnumContext, + &InterfaceData, + DetailData, + Length, + NULL, + &DeviceData); + + if (!Result) + { + return MM_STATUS_UNSUCCESSFUL; + } + + // copy path + *DeviceName = (LPWSTR)&DetailData->DevicePath[0]; + return Open(DetailData->DevicePath, OutHandle); +} + +BOOL +WdmAudInitUserModeMixer() +{ + HDEVINFO DeviceHandle; + MIXER_STATUS Status; + + /* create a device list */ + DeviceHandle = SetupDiGetClassDevs(&CategoryGuid, + NULL, + NULL, + DIGCF_DEVICEINTERFACE|DIGCF_PRESENT); + + if (DeviceHandle == INVALID_HANDLE_VALUE) + { + /* failed to create a device list */ + return FALSE; + } + + + /* initialize the mixer library */ + Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceHandle); + + /* free device list */ + SetupDiDestroyDeviceInfoList(DeviceHandle); + + if (Status != MM_STATUS_SUCCESS) + { + /* failed to initialize mixer library */ + DPRINT1("Failed to initialize mixer library with %x\n", Status); + return FALSE; + } + + /* completed successfully */ + return TRUE; +} + +ULONG +WdmAudGetMixerCount() +{ + /* return number of mixers available */ + return MMixerGetCount(&MixerContext); +} + +MMRESULT +WdmAudGetMixerCapabilties( + IN ULONG DeviceId, + LPMIXERCAPSW Capabilities) +{ + if (MMixerGetCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_BADDEVICEID; +} + +MMRESULT +WdmAudCloseMixer( + IN HMIXER Handle, + IN HANDLE hNotifyEvent) +{ + /* FIXME */ + return MMSYSERR_NOERROR; +} + +MMRESULT +WdmAudOpenMixer( + IN PHANDLE hMixer, + IN ULONG DeviceId, + IN HANDLE hNotifyEvent) +{ + if (MMixerOpen(&MixerContext, DeviceId, hNotifyEvent, NULL /* FIXME */, hMixer) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_BADDEVICEID; +} + +MMRESULT +WdmAudGetLineInfo( + IN HANDLE hMixer, + IN LPMIXERLINE MixLine, + IN ULONG Flags) +{ + if (MMixerGetLineInfo(&MixerContext, hMixer, Flags, MixLine) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_ERROR; +} + +MMRESULT +WdmAudGetLineControls( + IN HANDLE hMixer, + IN LPMIXERLINECONTROLSW MixControls, + IN ULONG Flags) +{ + if (MMixerGetLineControls(&MixerContext, hMixer, Flags, MixControls) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_ERROR; +} + +MMRESULT +WdmAudSetControlDetails( + IN HANDLE hMixer, + IN LPMIXERCONTROLDETAILS MixDetails, + IN ULONG Flags) +{ + if (MMixerSetControlDetails(&MixerContext, hMixer, Flags, MixDetails) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_ERROR; + +} + +MMRESULT +WdmAudGetControlDetails( + IN HANDLE hMixer, + IN LPMIXERCONTROLDETAILS MixDetails, + IN ULONG Flags) +{ + if (MMixerGetControlDetails(&MixerContext, hMixer, Flags, MixDetails) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_ERROR; +} diff --git a/reactos/dll/win32/wdmaud.drv/wdmaud.c b/reactos/dll/win32/wdmaud.drv/wdmaud.c index 9d3922f01e3..41211da1b8b 100644 --- a/reactos/dll/win32/wdmaud.drv/wdmaud.c +++ b/reactos/dll/win32/wdmaud.drv/wdmaud.c @@ -12,15 +12,8 @@ * */ -#include -#include -#include -#include -#include +#include "wdmaud.h" -#include -#include -#include "interface.h" #define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud" @@ -29,6 +22,7 @@ PWSTR UnknownWaveOut = L"Wave Output"; PWSTR UnknownMidiIn = L"Midi Input"; PWSTR UnknownMidiOut = L"Midi Output"; + HANDLE KernelHandle = INVALID_HANDLE_VALUE; DWORD OpenCount = 0; @@ -48,6 +42,12 @@ GetNumWdmDevs( IN MMDEVICE_TYPE DeviceType, OUT DWORD* DeviceCount) { +#ifdef USE_MMIXER_LIB + + *DeviceCount = WdmAudGetMixerCount(); + return MMSYSERR_NOERROR; +#else + MMRESULT Result; WDMAUD_DEVICE_INFO DeviceInfo; @@ -76,6 +76,7 @@ GetNumWdmDevs( *DeviceCount = DeviceInfo.DeviceCount; return MMSYSERR_NOERROR; +#endif } MMRESULT @@ -102,6 +103,14 @@ GetWdmDeviceCapabilities( SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId); +#ifdef USE_MMIXER_LIB + if (DeviceType == MIXER_DEVICE_TYPE) + { + return WdmAudGetMixerCapabilties(DeviceId, (LPMIXERCAPSW)Capabilities); + } +#endif + + ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); DeviceInfo.DeviceType = DeviceType; DeviceInfo.DeviceIndex = DeviceId; @@ -250,6 +259,12 @@ CloseWdmSoundDevice( sizeof(WDMAUD_DEVICE_INFO), NULL); } +#ifdef USE_MMIXER_LIB + if (DeviceType == MIXER_DEVICE_TYPE) + { + return WdmAudCloseMixer(SoundDeviceInstance->Handle, SoundDeviceInstance->hNotifyEvent); + } +#endif SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_CLOSE_WDMAUD, @@ -360,16 +375,21 @@ SetWdmMixerDeviceFormat( WDMAUD_DEVICE_INFO DeviceInfo; HANDLE hThread; + + Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if ( ! Instance->hNotifyEvent ) + return MMSYSERR_NOMEM; + +#ifdef USE_MMIXER_LIB + return WdmAudOpenMixer(&Instance->Handle, DeviceId, Instance->hNotifyEvent); +#endif + if (Instance->Handle != KernelHandle) { /* device is already open */ return MMSYSERR_NOERROR; } - Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if ( ! Instance->hNotifyEvent ) - return MMSYSERR_NOMEM; - Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if ( ! Instance->hStopEvent ) return MMSYSERR_NOMEM; @@ -807,6 +827,26 @@ QueryMixerInfo( MixControls = (LPMIXERLINECONTROLSW)Parameter; MixDetails = (LPMIXERCONTROLDETAILS)Parameter; +#ifdef USE_MMIXER_LIB + switch(uMsg) + { + case MXDM_GETLINEINFO: + return WdmAudGetLineInfo(SoundDeviceInstance->Handle, MixLine, Flags); + case MXDM_GETLINECONTROLS: + return WdmAudGetLineControls(SoundDeviceInstance->Handle, MixControls, Flags); + case MXDM_SETCONTROLDETAILS: + return WdmAudSetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags); + break; + case MXDM_GETCONTROLDETAILS: + return WdmAudGetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags); + break; + default: + SND_ASSERT(0); + return MMSYSERR_NOTSUPPORTED; + } +#endif + + switch(uMsg) { case MXDM_GETLINEINFO: @@ -1040,6 +1080,9 @@ BOOL WINAPI DllMain( switch ( fdwReason ) { case DLL_PROCESS_ATTACH : +#ifdef USE_MMIXER_LIB + WdmAudInitUserModeMixer(); +#endif SND_TRACE(L"WDMAUD.DRV - Process attached\n"); break; case DLL_PROCESS_DETACH : diff --git a/reactos/dll/win32/wdmaud.drv/wdmaud.h b/reactos/dll/win32/wdmaud.drv/wdmaud.h new file mode 100644 index 00000000000..366c17a1e78 --- /dev/null +++ b/reactos/dll/win32/wdmaud.drv/wdmaud.h @@ -0,0 +1,63 @@ +#ifndef WDMAUD_H__ +#define WDMAUD_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "interface.h" +#include "mmixer.h" +#include + +BOOL +WdmAudInitUserModeMixer(); + +ULONG +WdmAudGetMixerCount(); + +MMRESULT +WdmAudGetMixerCapabilties( + IN ULONG DeviceId, + LPMIXERCAPSW Capabilities); + +MMRESULT +WdmAudCloseMixer( + IN HMIXER Handle, + IN HANDLE hNotifyEvent); + +MMRESULT +WdmAudOpenMixer( + IN PHANDLE hMixer, + IN ULONG DeviceId, + IN HANDLE hNotifyEvent); + +MMRESULT +WdmAudGetLineInfo( + IN HANDLE hMixer, + IN LPMIXERLINE MixLine, + IN ULONG Flags); + +MMRESULT +WdmAudGetLineControls( + IN HANDLE hMixer, + IN LPMIXERLINECONTROLSW MixControls, + IN ULONG Flags); + +MMRESULT +WdmAudSetControlDetails( + IN HANDLE hMixer, + IN LPMIXERCONTROLDETAILS MixDetails, + IN ULONG Flags); + +MMRESULT +WdmAudGetControlDetails( + IN HANDLE hMixer, + IN LPMIXERCONTROLDETAILS MixDetails, + IN ULONG Flags); + +#endif diff --git a/reactos/dll/win32/wdmaud.drv/wdmaud.rbuild b/reactos/dll/win32/wdmaud.drv/wdmaud.rbuild index c6cf6abff82..a2d0ccc5a9a 100644 --- a/reactos/dll/win32/wdmaud.drv/wdmaud.rbuild +++ b/reactos/dll/win32/wdmaud.drv/wdmaud.rbuild @@ -3,6 +3,7 @@ . include/reactos/libs/sound . + . . 1 @@ -13,7 +14,10 @@ advapi32 libsamplerate msvcrt + mmixer + setupapi wdmaud.c mixer.c + mmixer.c wdmaud.rc