mirror of
https://github.com/reactos/reactos.git
synced 2025-04-25 16:10:29 +00:00
[WDMAUD.DRV]
- Integrate mmixer library into wdmaud.drv - Library is not yet used svn path=/trunk/; revision=44562
This commit is contained in:
parent
bc65426abe
commit
98826b3fe1
4 changed files with 451 additions and 12 deletions
329
reactos/dll/win32/wdmaud.drv/mmixer.c
Normal file
329
reactos/dll/win32/wdmaud.drv/mmixer.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -12,15 +12,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <ntddsnd.h>
|
||||
#include <sndtypes.h>
|
||||
#include <mmddk.h>
|
||||
#include <mmebuddy.h>
|
||||
#include "wdmaud.h"
|
||||
|
||||
#include <ks.h>
|
||||
#include <ksmedia.h>
|
||||
#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 :
|
||||
|
|
63
reactos/dll/win32/wdmaud.drv/wdmaud.h
Normal file
63
reactos/dll/win32/wdmaud.drv/wdmaud.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
#ifndef WDMAUD_H__
|
||||
#define WDMAUD_H__
|
||||
|
||||
#include <windows.h>
|
||||
#include <ntddsnd.h>
|
||||
#include <sndtypes.h>
|
||||
#include <setupapi.h>
|
||||
#include <mmddk.h>
|
||||
#include <mmebuddy.h>
|
||||
|
||||
#include <ks.h>
|
||||
#include <ksmedia.h>
|
||||
#include "interface.h"
|
||||
#include "mmixer.h"
|
||||
#include <debug.h>
|
||||
|
||||
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
|
|
@ -3,6 +3,7 @@
|
|||
<include base="wdmaud.drv">.</include>
|
||||
<include base="ReactOS">include/reactos/libs/sound</include>
|
||||
<include base="wdmaud_kernel">.</include>
|
||||
<include base="mmixer">.</include>
|
||||
<include base="libsamplerate">.</include>
|
||||
<define name="NDEBUG">1</define>
|
||||
<!-- <define name="USERMODE_MIXER" /> Enable this line to for usermode mixing support -->
|
||||
|
@ -13,7 +14,10 @@
|
|||
<library>advapi32</library>
|
||||
<library>libsamplerate</library>
|
||||
<library>msvcrt</library>
|
||||
<library>mmixer</library>
|
||||
<library>setupapi</library>
|
||||
<file>wdmaud.c</file>
|
||||
<file>mixer.c</file>
|
||||
<file>mmixer.c</file>
|
||||
<file>wdmaud.rc</file>
|
||||
</module>
|
||||
|
|
Loading…
Reference in a new issue