[WDMAUD_KERNEL]

- Replace mixer / wave support code by mmixer library
[MMIXER]
- Compare device name from 2 character onwards as there are difference in paths in user mode / kernel mode
- Invoke create pin callback if the caller provides it
[WDMAUD.DRV]
- Apply changes from mmixer library

-- Tested in Vbox with Winamp / ReactOS mplay32

svn path=/trunk/; revision=45579
This commit is contained in:
Johannes Anderwald 2010-02-11 21:04:57 +00:00
parent bfa7d233cd
commit a19cbab2fc
13 changed files with 891 additions and 3321 deletions

View file

@ -156,7 +156,7 @@ dll\directx\dinput8\dinput8.dll 1
dll\directx\dmusic\dmusic.dll 1
dll\directx\dplay\dplay.dll 1
dll\directx\dplayx\dplayx.dll 1
dll\directx\dsound\dsound.dll 1
dll\directx\dsound_new\dsound.dll 1
dll\directx\dxdiagn\dxdiagn.dll 1
dll\directx\wine\ddraw\ddraw.dll 1
dll\directx\d3d8thk\d3d8thk.dll 1
@ -515,7 +515,7 @@ drivers\storage\ide\pciidex\pciidex.sys 2
;drivers\usb\miniport\usbuhci\usbuhci.sys 2
;drivers\usb\usbhub\usbhub.sys 2
;drivers\usb\usbport\usbport.sys 2
drivers\usb\nt4compat\usbdriver\usbdriver.sys 2
;drivers\usb\nt4compat\usbdriver\usbdriver.sys 2
drivers\video\displays\vga\vgaddi.dll 1
drivers\video\displays\framebuf\framebuf.dll 1
@ -528,6 +528,7 @@ drivers\wdm\audio\filters\kmixer\kmixer.sys 2
drivers\wdm\audio\sysaudio\sysaudio.sys 2
drivers\wdm\audio\legacy\wdmaud\wdmaud.sys 2
drivers\wdm\audio\backpln\portcls\portcls.sys 2
drivers\wdm\audio\backpln\audio_test\audio_test.exe 1
drivers\wdm\audio\drm\drmk\drmk.sys 2
drivers\wmi\wmilib.sys 2
@ -798,4 +799,21 @@ modules\rostests\winetests\wintrust\wintrust_winetest.exe 7 o
modules\rostests\winetests\wlanapi\wlanapi_winetest.exe 7 optional
modules\rostests\winetests\ws2_32\ws2_32_winetest.exe 7 optional
modules\wallpaper\Angelus_02_ROSWP.bmp 4 optional
modules\windows\alcxwdm.sys 2 optional
modules\windows\dlkfet5b.sys 2 optional
modules\windows\cmaudio.sys 2 optional
modules\windows\cmaudio.inf 6 optional
;modules\windows\es1370mp.sys 2 optional
;modules\windows\es1371mp.sys 2 optional
modules\windows\alcxwdm.inf 6 optional
modules\windows\netdlfet.inf 6 optional
modules\windows\ks.inf 6 optional
;modules\windows\wdma_ens.inf 6 optional
modules\windows\b.mp3 7 optional
modules\windows\winamp.exe 7 optional
modules\windows\windows.wav 7 optional
modules\windows\D530.exe 7 optional
modules\windows\vmaudio.sys 2 optional
modules\windows\vmaudio.inf 6 optional

View file

@ -467,7 +467,7 @@ WdmAudSetWdmWaveDeviceFormatByMMixer(
bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE);
if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, &Instance->Handle) == MM_STATUS_SUCCESS)
if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, NULL, NULL, &Instance->Handle) == MM_STATUS_SUCCESS)
{
if (DeviceType == WAVE_OUT_DEVICE_TYPE)
{

View file

@ -8,17 +8,7 @@
*/
#include "wdmaud.h"
const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
NTSTATUS
WdmAudControlOpen(
@ -55,15 +45,15 @@ WdmAudControlDeviceType(
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
{
Result = DeviceExtension->MixerInfoCount;
Result = WdmAudGetMixerDeviceCount();
}
else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
{
Result = DeviceExtension->WaveOutDeviceCount;
Result = WdmAudGetWaveInDeviceCount();
}
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
{
Result = DeviceExtension->WaveInDeviceCount;
Result = WdmAudGetWaveOutDeviceCount();
}
/* store result count */
@ -221,7 +211,6 @@ WdmAudGetDeviceInterface(
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
LPWSTR Device;
LPWAVE_INFO WaveInfo;
ULONG Size, Length;
/* get device extension */
@ -233,7 +222,7 @@ WdmAudGetDeviceInterface(
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
{
/* get wave info */
Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo);
Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
/* check for success */
if (!NT_SUCCESS(Status))
@ -242,14 +231,6 @@ WdmAudGetDeviceInterface(
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
}
Status = GetSysAudioDevicePnpName(DeviceObject, WaveInfo->FilterId, &Device);
/* check for success */
if (!NT_SUCCESS(Status))
{
/* invalid device id */
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
}
/* calculate length */
Length = (wcslen(Device)+1) * sizeof(WCHAR);
@ -275,13 +256,13 @@ WdmAudGetDeviceInterface(
}
else if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
{
if (DeviceInfo->DeviceIndex >= DeviceExtension->MixerInfoCount)
if (DeviceInfo->DeviceIndex >= WdmAudGetMixerDeviceCount())
{
/* invalid device id */
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
}
Status = GetSysAudioDevicePnpName(DeviceObject, DeviceExtension->MixerInfo[DeviceInfo->DeviceIndex].DeviceIndex, &Device);
Status = WdmAudGetMixerPnpNameByIndex(DeviceInfo->DeviceIndex, &Device);
/* check for success */
if (!NT_SUCCESS(Status))
{
@ -308,8 +289,6 @@ WdmAudGetDeviceInterface(
//FIXME SEH
RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
}
ExFreePool(Device);
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
}

View file

@ -80,9 +80,7 @@ WdmAudInstallDevice(
}
Status = WdmAudMixerInitialize(DeviceObject);
DPRINT("WdmAudMixerInitialize Status %x\n", Status);
Status = WdmAudWaveInitialize(DeviceObject);
DPRINT("WdmAudWaveInitialize Status %x\n", Status);
DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount());
DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,663 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/wdmaud/mmixer.c
* PURPOSE: WDM Legacy Mixer
* PROGRAMMER: 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, OUT PHANDLE OutKey);
MIXER_STATUS OpenKey(IN HANDLE hKey, IN LPWSTR SubKey, IN ULONG DesiredAccess, OUT PHANDLE OutKey);
MIXER_STATUS CloseKey(IN HANDLE hKey);
MIXER_STATUS QueryKeyValue(IN HANDLE hKey, IN LPWSTR KeyName, OUT PVOID * ResultBuffer, OUT PULONG ResultLength, OUT PULONG KeyType);
PVOID AllocEventData(IN ULONG ExtraSize);
VOID FreeEventData(IN PVOID EventData);
MIXER_CONTEXT MixerContext =
{
sizeof(MIXER_CONTEXT),
NULL,
Alloc,
Control,
Free,
Open,
Close,
Copy,
OpenKey,
QueryKeyValue,
CloseKey,
AllocEventData,
FreeEventData
};
GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO};
MIXER_STATUS
QueryKeyValue(
IN HANDLE hKey,
IN LPWSTR lpKeyName,
OUT PVOID * ResultBuffer,
OUT PULONG ResultLength,
OUT PULONG KeyType)
{
NTSTATUS Status;
UNICODE_STRING KeyName;
ULONG Length;
PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
/* initialize key name */
RtlInitUnicodeString(&KeyName, lpKeyName);
/* now query MatchingDeviceId key */
Status = ZwQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, NULL, 0, &Length);
/* check for success */
if (Status != STATUS_BUFFER_TOO_SMALL)
return MM_STATUS_UNSUCCESSFUL;
/* allocate a buffer for key data */
PartialInformation = ExAllocatePool(NonPagedPool, Length);
if (!PartialInformation)
return MM_STATUS_NO_MEMORY;
/* now query MatchingDeviceId key */
Status = ZwQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length);
/* check for success */
if (!NT_SUCCESS(Status))
{
ExFreePool(PartialInformation);
return MM_STATUS_UNSUCCESSFUL;
}
if (KeyType)
{
/* return key type */
*KeyType = PartialInformation->Type;
}
if (ResultLength)
{
/* return data length */
*ResultLength = PartialInformation->DataLength;
}
*ResultBuffer = ExAllocatePool(NonPagedPool, PartialInformation->DataLength);
if (!*ResultBuffer)
{
/* not enough memory */
ExFreePool(PartialInformation);
return MM_STATUS_NO_MEMORY;
}
/* copy key value */
RtlMoveMemory(*ResultBuffer, PartialInformation->Data, PartialInformation->DataLength);
/* free key info */
ExFreePool(PartialInformation);
return MM_STATUS_SUCCESS;
}
MIXER_STATUS
OpenKey(
IN HANDLE hKey,
IN LPWSTR lpSubKeyName,
IN ULONG DesiredAccess,
OUT PHANDLE OutKey)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SubKeyName;
NTSTATUS Status;
/* initialize sub key name */
RtlInitUnicodeString(&SubKeyName, lpSubKeyName);
/* initialize key attributes */
InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, hKey, NULL);
/* open the key */
Status = ZwOpenKey(OutKey, DesiredAccess, &ObjectAttributes);
if (NT_SUCCESS(Status))
return MM_STATUS_SUCCESS;
else
return MM_STATUS_UNSUCCESSFUL;
}
MIXER_STATUS
CloseKey(
IN HANDLE hKey)
{
if (ZwClose(hKey) == STATUS_SUCCESS)
return MM_STATUS_SUCCESS;
else
return MM_STATUS_UNSUCCESSFUL;
}
PVOID Alloc(ULONG NumBytes)
{
PVOID Mem = ExAllocatePool(NonPagedPool, NumBytes);
if (!Mem)
return Mem;
RtlZeroMemory(Mem, NumBytes);
return Mem;
}
MIXER_STATUS
Close(HANDLE hDevice)
{
if (ZwClose(hDevice) == STATUS_SUCCESS)
return MM_STATUS_SUCCESS;
else
return MM_STATUS_UNSUCCESSFUL;
}
VOID
Free(PVOID Block)
{
ExFreePool(Block);
}
VOID
Copy(PVOID Src, PVOID Dst, ULONG NumBytes)
{
RtlMoveMemory(Src, Dst, NumBytes);
}
MIXER_STATUS
Open(
IN LPWSTR DevicePath,
OUT PHANDLE hDevice)
{
if (WdmAudOpenSysAudioDevice(DevicePath, hDevice) == STATUS_SUCCESS)
return MM_STATUS_SUCCESS;
else
return MM_STATUS_UNSUCCESSFUL;
}
MIXER_STATUS
Control(
IN HANDLE hMixer,
IN ULONG dwIoControlCode,
IN PVOID lpInBuffer,
IN ULONG nInBufferSize,
OUT PVOID lpOutBuffer,
ULONG nOutBufferSize,
PULONG lpBytesReturned)
{
NTSTATUS Status;
PFILE_OBJECT FileObject;
/* get file object */
Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("failed to reference %p with %lx\n", hMixer, Status);
return MM_STATUS_UNSUCCESSFUL;
}
/* perform request */
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned);
/* release object reference */
ObDereferenceObject(FileObject);
if (Status == STATUS_MORE_ENTRIES || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
{
/* more data is available */
return MM_STATUS_MORE_ENTRIES;
}
else if (Status == STATUS_SUCCESS)
{
/* operation succeeded */
return MM_STATUS_SUCCESS;
}
else
{
DPRINT("Failed with %lx\n", Status);
return MM_STATUS_UNSUCCESSFUL;
}
}
MIXER_STATUS
Enum(
IN PVOID EnumContext,
IN ULONG DeviceIndex,
OUT LPWSTR * DeviceName,
OUT PHANDLE OutHandle,
OUT PHANDLE OutKey)
{
PDEVICE_OBJECT DeviceObject;
ULONG DeviceCount;
NTSTATUS Status;
UNICODE_STRING KeyName;
/* get enumeration context */
DeviceObject = (PDEVICE_OBJECT)EnumContext;
/* get device count */
DeviceCount = GetSysAudioDeviceCount(DeviceObject);
if (DeviceIndex >= DeviceCount)
{
/* no more devices */
return MM_STATUS_NO_MORE_DEVICES;
}
/* get device name */
Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, DeviceName);
if (!NT_SUCCESS(Status))
{
/* failed to retrieve device name */
return MM_STATUS_UNSUCCESSFUL;
}
/* intialize key name */
RtlInitUnicodeString(&KeyName, *DeviceName);
/* open device interface key */
Status = IoOpenDeviceInterfaceRegistryKey(&KeyName, GENERIC_READ | GENERIC_WRITE, OutKey);
#if 0
if (!NT_SUCCESS(Status))
{
/* failed to open key */
DPRINT("IoOpenDeviceInterfaceRegistryKey failed with %lx\n", Status);
ExFreePool(*DeviceName);
return MM_STATUS_UNSUCCESSFUL;
}
#endif
/* open device handle */
Status = OpenDevice(*DeviceName, OutHandle, NULL);
if (!NT_SUCCESS(Status))
{
/* failed to open device */
return MM_STATUS_UNSUCCESSFUL;
}
return MM_STATUS_SUCCESS;
}
PVOID
AllocEventData(
IN ULONG ExtraSize)
{
PKSEVENTDATA Data = (PKSEVENTDATA)ExAllocatePool(NonPagedPool, sizeof(KSEVENTDATA) + ExtraSize);
if (!Data)
return NULL;
Data->EventObject.Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
if (!Data->EventHandle.Event)
{
ExFreePool(Data);
return NULL;
}
KeInitializeEvent(Data->EventObject.Event, NotificationEvent, FALSE);
Data->NotificationType = KSEVENTF_EVENT_HANDLE;
return Data;
}
VOID
FreeEventData(IN PVOID EventData)
{
PKSEVENTDATA Data = (PKSEVENTDATA)EventData;
ExFreePool(Data->EventHandle.Event);
ExFreePool(Data);
}
NTSTATUS
WdmAudMixerInitialize(
IN PDEVICE_OBJECT DeviceObject)
{
MIXER_STATUS Status;
/* initialize the mixer library */
Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceObject);
if (Status != MM_STATUS_SUCCESS)
{
/* failed to initialize mmixer library */
DPRINT("MMixerInitialize failed with %lx\n", Status);
}
return Status;
}
NTSTATUS
WdmAudMixerCapabilities(
IN PDEVICE_OBJECT DeviceObject,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo,
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
{
if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS)
return STATUS_SUCCESS;
return STATUS_INVALID_PARAMETER;
}
NTSTATUS
WdmAudControlOpenMixer(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
HANDLE hMixer;
PWDMAUD_HANDLE Handles;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
PKEVENT EventObject = NULL;
DPRINT("WdmAudControlOpenMixer\n");
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (DeviceInfo->u.hNotifyEvent)
{
Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo);
DbgBreakPoint();
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
}
if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, EventObject, NULL /* FIXME */, &hMixer) != MM_STATUS_SUCCESS)
{
ObDereferenceObject(EventObject);
DPRINT1("Failed to open mixer\n");
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
Handles = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1));
if (Handles)
{
if (ClientInfo->NumPins)
{
RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins);
ExFreePool(ClientInfo->hPins);
}
ClientInfo->hPins = Handles;
ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer;
ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE;
ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject;
ClientInfo->NumPins++;
}
else
{
ObDereferenceObject(EventObject);
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
}
DeviceInfo->hDevice = hMixer;
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
NTAPI
WdmAudGetControlDetails(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
MIXER_STATUS Status;
/* clear hmixer type flag */
DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
/* query mmixer library */
Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
if (Status == MM_STATUS_SUCCESS)
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
else
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
NTAPI
WdmAudGetLineInfo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
MIXER_STATUS Status;
/* clear hmixer type flag */
DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
/* query mixer library */
Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixLine);
if (Status == MM_STATUS_SUCCESS)
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
else
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
NTAPI
WdmAudGetLineControls(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
MIXER_STATUS Status;
/* clear hmixer type flag */
DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
/* query mixer library */
Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixControls);
if (Status == MM_STATUS_SUCCESS)
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
else
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
NTAPI
WdmAudSetControlDetails(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
MIXER_STATUS Status;
/* clear hmixer type flag */
DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
/* query mixer library */
Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
if (Status == MM_STATUS_SUCCESS)
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
else
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
NTAPI
WdmAudGetMixerEvent(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
UNIMPLEMENTED
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
}
ULONG
WdmAudGetMixerDeviceCount()
{
return MMixerGetCount(&MixerContext);
}
ULONG
WdmAudGetWaveInDeviceCount()
{
return MMixerGetWaveInCount(&MixerContext);
}
ULONG
WdmAudGetWaveOutDeviceCount()
{
return MMixerGetWaveOutCount(&MixerContext);
}
NTSTATUS
WdmAudGetMixerPnpNameByIndex(
IN ULONG DeviceIndex,
OUT LPWSTR * Device)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
WdmAudGetPnpNameByIndexAndType(
IN ULONG DeviceIndex,
IN SOUND_DEVICE_TYPE DeviceType,
OUT LPWSTR *Device)
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
WdmAudWaveCapabilities(
IN PDEVICE_OBJECT DeviceObject,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo,
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
{
MIXER_STATUS Status;
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
{
/* get capabilities */
Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps);
}
else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
{
/* get capabilities */
Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps);
}
else
{
ASSERT(0);
return STATUS_UNSUCCESSFUL;
}
if (Status == MM_STATUS_SUCCESS)
return STATUS_SUCCESS;
else
return STATUS_UNSUCCESSFUL;
}
MIXER_STATUS
CreatePinCallback(
IN PVOID Ctx,
IN ULONG VirtualDeviceId,
IN ULONG PinId,
IN HANDLE hFilter,
IN PKSPIN_CONNECT PinConnect,
IN ACCESS_MASK DesiredAccess,
OUT PHANDLE PinHandle)
{
ULONG BytesReturned;
SYSAUDIO_INSTANCE_INFO InstanceInfo;
NTSTATUS Status;
ULONG FreeIndex;
PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx;
/* setup property request */
InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
InstanceInfo.Flags = 0;
InstanceInfo.DeviceNumber = VirtualDeviceId;
/* attach to virtual device */
Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
if (!NT_SUCCESS(Status))
return MM_STATUS_UNSUCCESSFUL;
/* close existing pin */
FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType);
/* now create the pin */
Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);
/* check for success */
if (!NT_SUCCESS(Status))
return MM_STATUS_UNSUCCESSFUL;
/* store the handle */
Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex);
if (!NT_SUCCESS(Status))
{
/* failed to insert handle */
ZwClose(*PinHandle);
return MM_STATUS_UNSUCCESSFUL;
}
return MM_STATUS_SUCCESS;
}
NTSTATUS
WdmAudControlOpenWave(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
MIXER_STATUS Status;
PIN_CREATE_CONTEXT Context;
Context.ClientInfo = ClientInfo;
Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Context.DeviceType = DeviceInfo->DeviceType;
Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice);
if (Status == MM_STATUS_SUCCESS)
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
else
return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
}

View file

@ -2,12 +2,37 @@
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/wdmaud/sup.c
* PURPOSE: System Audio graph builder
* PURPOSE: Misc support routines
* PROGRAMMER: Andrew Greenwood
* Johannes Anderwald
*/
#include "wdmaud.h"
ULONG
GetSysAudioDeviceCount(
IN PDEVICE_OBJECT DeviceObject)
{
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
KSPROPERTY Pin;
ULONG Count, BytesReturned;
NTSTATUS Status;
/* setup the query request */
Pin.Set = KSPROPSETID_Sysaudio;
Pin.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
Pin.Flags = KSPROPERTY_TYPE_GET;
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* query sysaudio for the device count */
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
if (!NT_SUCCESS(Status))
return 0;
return Count;
}
NTSTATUS
SetIrpIoStatus(
IN PIRP Irp,
@ -21,7 +46,7 @@ SetIrpIoStatus(
}
NTSTATUS
ULONG
ClosePin(
IN PWDMAUD_CLIENT ClientInfo,
IN ULONG FilterId,
@ -298,3 +323,83 @@ FindProductName(
return Status;
}
NTSTATUS
GetSysAudioDevicePnpName(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG DeviceIndex,
OUT LPWSTR * Device)
{
ULONG BytesReturned;
KSP_PIN Pin;
NTSTATUS Status;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
/* first check if the device index is within bounds */
if (DeviceIndex >= GetSysAudioDeviceCount(DeviceObject))
return STATUS_INVALID_PARAMETER;
/* setup the query request */
Pin.Property.Set = KSPROPSETID_Sysaudio;
Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME;
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
Pin.PinId = DeviceIndex;
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* query sysaudio for the device path */
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), NULL, 0, &BytesReturned);
/* check if the request failed */
if (Status != STATUS_BUFFER_TOO_SMALL || BytesReturned == 0)
return STATUS_UNSUCCESSFUL;
/* allocate buffer for the device */
*Device = ExAllocatePool(NonPagedPool, BytesReturned);
if (!Device)
return STATUS_INSUFFICIENT_RESOURCES;
/* query sysaudio again for the device path */
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), (PVOID)*Device, BytesReturned, &BytesReturned);
if (!NT_SUCCESS(Status))
{
/* failed */
ExFreePool(*Device);
return Status;
}
return Status;
}
NTSTATUS
OpenDevice(
IN LPWSTR Device,
OUT PHANDLE DeviceHandle,
OUT PFILE_OBJECT * FileObject)
{
NTSTATUS Status;
HANDLE hDevice;
/* now open the device */
Status = WdmAudOpenSysAudioDevice(Device, &hDevice);
if (!NT_SUCCESS(Status))
{
return Status;
}
*DeviceHandle = hDevice;
if (FileObject)
{
Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL);
if (!NT_SUCCESS(Status))
{
ZwClose(hDevice);
}
}
return Status;
}

View file

@ -1,756 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/wdmaud/wave.c
* PURPOSE: Wave Out enumeration
* PROGRAMMER: Andrew Greenwood
* Johannes Anderwald
*/
#include "wdmaud.h"
typedef struct
{
ULONG SampleRate;
ULONG Bit8Mono;
ULONG Bit8Stereo;
ULONG Bit16Mono;
ULONG Bit16Stereo;
}AUDIO_RANGE;
#define AUDIO_TEST_RANGE (5)
static AUDIO_RANGE TestRange[AUDIO_TEST_RANGE] =
{
{
11025,
WAVE_FORMAT_1M08,
WAVE_FORMAT_1S08,
WAVE_FORMAT_1M16,
WAVE_FORMAT_1S16
},
{
22050,
WAVE_FORMAT_2M08,
WAVE_FORMAT_2S08,
WAVE_FORMAT_2M16,
WAVE_FORMAT_2S16
},
{
44100,
WAVE_FORMAT_4M08,
WAVE_FORMAT_4S08,
WAVE_FORMAT_4M16,
WAVE_FORMAT_4S16
},
{
48000,
WAVE_FORMAT_48M08,
WAVE_FORMAT_48S08,
WAVE_FORMAT_48M16,
WAVE_FORMAT_48S16
},
{
96000,
WAVE_FORMAT_96M08,
WAVE_FORMAT_96S08,
WAVE_FORMAT_96M16,
WAVE_FORMAT_96S16
}
};
LPWAVE_INFO
AllocateWaveInfo()
{
/* allocate wav info */
LPWAVE_INFO WaveOutInfo = ExAllocatePool(NonPagedPool, sizeof(WAVE_INFO));
if (!WaveOutInfo)
return NULL;
/* zero wave info struct */
RtlZeroMemory(WaveOutInfo, sizeof(WAVE_INFO));
return WaveOutInfo;
}
PKSPIN_CONNECT
AllocatePinConnect(
ULONG DataFormatSize)
{
PKSPIN_CONNECT Connect = ExAllocatePool(NonPagedPool, sizeof(KSPIN_CONNECT) + DataFormatSize);
if (!Connect)
return NULL;
/* zero pin connect struct */
RtlZeroMemory(Connect, sizeof(KSPIN_CONNECT) + DataFormatSize);
return Connect;
}
NTSTATUS
GetWaveInfoByIndexAndType(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG DeviceIndex,
IN SOUND_DEVICE_TYPE DeviceType,
OUT LPWAVE_INFO *OutWaveInfo)
{
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
ULONG Index = 0;
PLIST_ENTRY Entry, ListHead;
LPWAVE_INFO WaveInfo;
/* get device extension */
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (DeviceType == WAVE_IN_DEVICE_TYPE)
ListHead = &DeviceExtension->WaveInList;
else
ListHead = &DeviceExtension->WaveOutList;
/* get first entry */
Entry = ListHead->Flink;
while(Entry != ListHead)
{
WaveInfo = (LPWAVE_INFO)CONTAINING_RECORD(Entry, WAVE_INFO, Entry);
if (Index == DeviceIndex)
{
*OutWaveInfo = WaveInfo;
return STATUS_SUCCESS;
}
Index++;
Entry = Entry->Flink;
}
return STATUS_NOT_FOUND;
}
VOID
InitializePinConnect(
IN OUT PKSPIN_CONNECT PinConnect,
IN ULONG PinId)
{
PinConnect->Interface.Set = KSINTERFACESETID_Standard;
PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
PinConnect->Interface.Flags = 0;
PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
PinConnect->Medium.Flags = 0;
PinConnect->PinToHandle = NULL;
PinConnect->PinId = PinId;
PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
PinConnect->Priority.PrioritySubClass = 1;
}
VOID
InitializeDataFormat(
IN PKSDATAFORMAT_WAVEFORMATEX DataFormat,
LPWAVEFORMATEX WaveFormatEx)
{
DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag;
DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels;
DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec;
DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign;
DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec;
DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample;
DataFormat->WaveFormatEx.cbSize = 0;
DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
DataFormat->DataFormat.Flags = 0;
DataFormat->DataFormat.Reserved = 0;
DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
DataFormat->DataFormat.SampleSize = 4;
}
NTSTATUS
AttachToVirtualAudioDevice(
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,
IN ULONG VirtualDeviceId)
{
ULONG BytesReturned;
SYSAUDIO_INSTANCE_INFO InstanceInfo;
/* setup property request */
InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
InstanceInfo.Flags = 0;
InstanceInfo.DeviceNumber = VirtualDeviceId;
/* attach to virtual device */
return KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
}
NTSTATUS
GetAudioPinDataRanges(
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,
IN ULONG FilterId,
IN ULONG PinId,
IN OUT PKSMULTIPLE_ITEM * OutMultipleItem)
{
KSP_PIN PinProperty;
ULONG BytesReturned = 0;
NTSTATUS Status;
PKSMULTIPLE_ITEM MultipleItem;
/* retrieve size of data ranges buffer */
PinProperty.Reserved = FilterId;
PinProperty.PinId = PinId;
PinProperty.Property.Set = KSPROPSETID_Pin;
PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES;
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned);
if (Status != STATUS_MORE_ENTRIES)
{
return Status;
}
MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
if (!MultipleItem)
{
/* not enough memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
if (!NT_SUCCESS(Status))
{
/* failed */
ExFreePool(MultipleItem);
return Status;
}
/* save result */
*OutMultipleItem = MultipleItem;
return Status;
}
NTSTATUS
FindAudioDataRange(
PKSMULTIPLE_ITEM MultipleItem,
PKSDATARANGE_AUDIO * OutDataRangeAudio)
{
ULONG Index;
PKSDATARANGE_AUDIO DataRangeAudio;
PKSDATARANGE DataRange;
DataRange = (PKSDATARANGE) (MultipleItem + 1);
for(Index = 0; Index < MultipleItem->Count; Index++)
{
if (DataRange->FormatSize == sizeof(KSDATARANGE_AUDIO))
{
DataRangeAudio = (PKSDATARANGE_AUDIO)DataRange;
if (IsEqualGUIDAligned(&DataRangeAudio->DataRange.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) &&
IsEqualGUIDAligned(&DataRangeAudio->DataRange.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) &&
IsEqualGUIDAligned(&DataRangeAudio->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
{
DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio->MinimumSampleFrequency, DataRangeAudio->MaximumSampleFrequency,
DataRangeAudio->MinimumBitsPerSample, DataRangeAudio->MaximumBitsPerSample, DataRangeAudio->MaximumChannels);
*OutDataRangeAudio = DataRangeAudio;
return STATUS_SUCCESS;
}
}
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
OpenWavePin(
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,
IN ULONG FilterId,
IN ULONG PinId,
IN LPWAVEFORMATEX WaveFormatEx,
IN ACCESS_MASK DesiredAccess,
OUT PHANDLE PinHandle)
{
PKSPIN_CONNECT PinConnect;
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
NTSTATUS Status;
/* allocate pin connect */
PinConnect = AllocatePinConnect(sizeof(KSDATAFORMAT_WAVEFORMATEX));
if (!PinConnect)
{
/* no memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* initialize pin connect struct */
InitializePinConnect(PinConnect, PinId);
/* get offset to dataformat */
DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1);
/* initialize with requested wave format */
InitializeDataFormat(DataFormat, WaveFormatEx);
/* first attach to the virtual device */
Status = AttachToVirtualAudioDevice(DeviceExtension, FilterId);
if (!NT_SUCCESS(Status))
{
/* failed */
ExFreePool(PinConnect);
return Status;
}
/* now create the pin */
Status = KsCreatePin(DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);
/* free create info */
ExFreePool(PinConnect);
return Status;
}
ULONG
GetPinInstanceCount(
PWDMAUD_DEVICE_EXTENSION DeviceExtension,
ULONG FilterId,
ULONG PinId)
{
KSP_PIN PinRequest;
KSPIN_CINSTANCES PinInstances;
ULONG BytesReturned;
NTSTATUS Status;
/* query the instance count */
PinRequest.Reserved = FilterId;
PinRequest.PinId = PinId;
PinRequest.Property.Set = KSPROPSETID_Pin;
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
ASSERT(Status == STATUS_SUCCESS);
return PinInstances.CurrentCount;
}
NTSTATUS
CheckSampleFormat(
PWDMAUD_DEVICE_EXTENSION DeviceExtension,
LPWAVE_INFO WaveInfo,
ULONG SampleRate,
ULONG NumChannels,
ULONG BitsPerSample)
{
NTSTATUS Status = STATUS_SUCCESS;
#if 0
WAVEFORMATEX WaveFormat;
HANDLE PinHandle;
/* clear wave format */
RtlZeroMemory(&WaveFormat, sizeof(WAVEFORMATEX));
WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
WaveFormat.nChannels = NumChannels;
WaveFormat.nSamplesPerSec = SampleRate;
WaveFormat.nAvgBytesPerSec = SampleRate * NumChannels * (BitsPerSample/8);
WaveFormat.nBlockAlign = (NumChannels * BitsPerSample) / 8;
WaveFormat.wBitsPerSample = BitsPerSample;
WaveFormat.cbSize = sizeof(WAVEFORMATEX);
Status = OpenWavePin(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId, &WaveFormat, GENERIC_READ | GENERIC_WRITE, &PinHandle);
if (NT_SUCCESS(Status))
{
/* success */
ZwClose(PinHandle);
while(GetPinInstanceCount(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId))
KeStallExecutionProcessor(5);
}
DPRINT("SampleRate %u BitsPerSample %u NumChannels %u Status %x bInput %u\n", SampleRate, BitsPerSample, NumChannels, Status, WaveInfo->bInput);
#endif
return Status;
}
NTSTATUS
CheckFormat(
PWDMAUD_DEVICE_EXTENSION DeviceExtension,
PKSDATARANGE_AUDIO DataRangeAudio,
LPWAVE_INFO WaveInfo)
{
ULONG Index, SampleFrequency;
ULONG Result = 0;
NTSTATUS Status;
for(Index = 0; Index < AUDIO_TEST_RANGE; Index++)
{
SampleFrequency = TestRange[Index].SampleRate;
if (DataRangeAudio->MinimumSampleFrequency <= SampleFrequency && DataRangeAudio->MaximumSampleFrequency >= SampleFrequency)
{
/* the audio adapter supports the sample frequency */
if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8)
{
/* check if pin supports the sample rate in 8-Bit Mono */
Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 1, 8);
if (NT_SUCCESS(Status))
{
Result |= TestRange[Index].Bit8Mono;
}
if (DataRangeAudio->MaximumChannels > 1)
{
/* check if pin supports the sample rate in 8-Bit Stereo */
Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 2, 8);
if (NT_SUCCESS(Status))
{
Result |= TestRange[Index].Bit8Stereo;
}
}
}
if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16)
{
/* check if pin supports the sample rate in 16-Bit Mono */
Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 1, 16);
if (NT_SUCCESS(Status))
{
Result |= TestRange[Index].Bit16Mono;
}
if (DataRangeAudio->MaximumChannels > 1)
{
/* check if pin supports the sample rate in 16-Bit Stereo */
Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 2, 16);
if (NT_SUCCESS(Status))
{
Result |= TestRange[Index].Bit16Stereo;
}
}
}
}
}
if (WaveInfo->bInput)
WaveInfo->u.InCaps.dwFormats = Result;
else
WaveInfo->u.OutCaps.dwFormats = Result;
DPRINT("Format %x bInput %u\n", Result, WaveInfo->bInput);
return STATUS_SUCCESS;
}
NTSTATUS
InitializeWaveInfo(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG FilterId,
IN ULONG PinId,
IN ULONG bInput)
{
KSP_PIN PinProperty;
KSCOMPONENTID ComponentId;
NTSTATUS Status;
ULONG BytesReturned;
WCHAR DeviceName[MAX_PATH];
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
PKSMULTIPLE_ITEM MultipleItem;
PKSDATARANGE_AUDIO DataRangeAudio;
LPWAVE_INFO WaveInfo = AllocateWaveInfo();
if (!WaveInfo)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize wave info */
WaveInfo->bInput = bInput;
WaveInfo->FilterId = FilterId;
WaveInfo->PinId = PinId;
/* setup request to return component id */
PinProperty.PinId = FilterId;
PinProperty.Property.Set = KSPROPSETID_Sysaudio;
PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_COMPONENT_ID;
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
/* get device extension */
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* query sysaudio for component id */
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
if (NT_SUCCESS(Status))
{
if (bInput)
{
WaveInfo->u.InCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
WaveInfo->u.InCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision);
}
else
{
WaveInfo->u.OutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
WaveInfo->u.OutCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision);
}
}
else
{
/* set up something useful */
if (bInput)
{
WaveInfo->u.InCaps.wMid = MM_MICROSOFT;
WaveInfo->u.InCaps.wPid = MM_PID_UNMAPPED;
WaveInfo->u.InCaps.vDriverVersion = 1;
}
else
{
WaveInfo->u.OutCaps.wMid = MM_MICROSOFT;
WaveInfo->u.OutCaps.wPid = MM_PID_UNMAPPED;
WaveInfo->u.OutCaps.vDriverVersion = 1;
}
}
/* retrieve pnp base name */
PinProperty.PinId = FilterId;
PinProperty.Property.Set = KSPROPSETID_Sysaudio;
PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME;
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)DeviceName, sizeof(DeviceName), &BytesReturned);
if (NT_SUCCESS(Status))
{
/* find product name */
if (bInput)
Status = FindProductName(DeviceName, MAXPNAMELEN, WaveInfo->u.OutCaps.szPname);
else
Status = FindProductName(DeviceName, MAXPNAMELEN, WaveInfo->u.InCaps.szPname);
/* check for success */
if (!NT_SUCCESS(Status))
{
if (bInput)
WaveInfo->u.OutCaps.szPname[0] = L'\0';
else
WaveInfo->u.InCaps.szPname[0] = L'\0';
}
}
Status = GetAudioPinDataRanges(DeviceExtension, FilterId, PinId, &MultipleItem);
if (NT_SUCCESS(Status))
{
/* find a audio data range */
Status = FindAudioDataRange(MultipleItem, &DataRangeAudio);
if (NT_SUCCESS(Status))
{
if (bInput)
{
WaveInfo->u.InCaps.wChannels = DataRangeAudio->MaximumChannels;
}
else
{
WaveInfo->u.OutCaps.wChannels = DataRangeAudio->MaximumChannels;
}
CheckFormat(DeviceExtension, DataRangeAudio, WaveInfo);
}
ExFreePool(MultipleItem);
}
if (bInput)
{
InsertTailList(&DeviceExtension->WaveInList, &WaveInfo->Entry);
DeviceExtension->WaveInDeviceCount++;
}
else
{
InsertTailList(&DeviceExtension->WaveOutList, &WaveInfo->Entry);
DeviceExtension->WaveOutDeviceCount++;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
WdmAudWaveInitialize(
IN PDEVICE_OBJECT DeviceObject)
{
KSP_PIN Pin;
ULONG Count, BytesReturned, Index, SubIndex, Result, NumPins;
NTSTATUS Status;
KSPIN_COMMUNICATION Communication;
KSPIN_DATAFLOW DataFlow;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
Pin.Property.Set = KSPROPSETID_Sysaudio;
Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* set wave count to zero */
DeviceExtension->WaveInDeviceCount = 0;
DeviceExtension->WaveOutDeviceCount = 0;
/* intialize list head */
InitializeListHead(&DeviceExtension->WaveInList);
InitializeListHead(&DeviceExtension->WaveOutList);
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
Result = 0;
for(Index = 0; Index < Count; Index++)
{
/* query number of pins */
Pin.Reserved = Index; // see sysaudio
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
Pin.Property.Set = KSPROPSETID_Pin;
Pin.Property.Id = KSPROPERTY_PIN_CTYPES;
Pin.PinId = 0;
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned);
if (NT_SUCCESS(Status))
{
/* enumerate now all pins */
for(SubIndex = 0; SubIndex < NumPins; SubIndex++)
{
Pin.PinId = SubIndex;
Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
Communication = KSPIN_COMMUNICATION_NONE;
/* get pin communication type */
KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW;
DataFlow = 0;
/* get pin dataflow type */
KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
{
/* found a wave out device */
InitializeWaveInfo(DeviceObject, Index, SubIndex, FALSE);
}
else if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
{
/* found a wave in device */
InitializeWaveInfo(DeviceObject, Index, SubIndex, TRUE);
}
}
}
}
return STATUS_SUCCESS;
}
NTSTATUS
WdmAudControlOpenWave(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
LPWAVE_INFO WaveInfo;
NTSTATUS Status;
ACCESS_MASK DesiredAccess = 0;
HANDLE PinHandle;
ULONG FreeIndex;
if (DeviceInfo->u.WaveFormatEx.wFormatTag != WAVE_FORMAT_PCM)
{
DPRINT("FIXME: Only WAVE_FORMAT_PCM is supported RequestFormat %x\n", DeviceInfo->u.WaveFormatEx.wFormatTag);
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
/* get device extension */
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* find destination wave */
Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo);
if (!NT_SUCCESS(Status))
{
/* failed to find wave info */
DbgBreakPoint();
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
/* close pin handle which uses same virtual audio device id and pin id */
FreeIndex = ClosePin(ClientInfo, WaveInfo->FilterId, WaveInfo->PinId, DeviceInfo->DeviceType);
/* get desired access */
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
{
DesiredAccess |= GENERIC_READ;
}
else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
{
DesiredAccess |= GENERIC_WRITE;
}
/* now try open the pin */
Status = OpenWavePin(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId, &DeviceInfo->u.WaveFormatEx, DesiredAccess, &PinHandle);
if (!NT_SUCCESS(Status))
{
/* failed to open the pin */
return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, 0);
}
/* store the handle */
Status = InsertPinHandle(ClientInfo, WaveInfo->FilterId, WaveInfo->PinId, DeviceInfo->DeviceType, PinHandle, FreeIndex);
if (!NT_SUCCESS(Status))
{
/* failed to insert handle */
ZwClose(PinHandle);
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
/* store pin handle */
DeviceInfo->hDevice = PinHandle;
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
}
NTSTATUS
WdmAudWaveCapabilities(
IN PDEVICE_OBJECT DeviceObject,
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo,
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
{
LPWAVE_INFO WaveInfo;
NTSTATUS Status;
/* find destination wave */
Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo);
if (!NT_SUCCESS(Status))
{
/* failed to find wave info */
DbgBreakPoint();
return STATUS_UNSUCCESSFUL;
}
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
{
RtlMoveMemory(&DeviceInfo->u.WaveInCaps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW));
}
else
{
RtlMoveMemory(&DeviceInfo->u.WaveOutCaps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW));
}
return STATUS_SUCCESS;
}

View file

@ -13,18 +13,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include "mmixer.h"
#include "interface.h"
typedef struct
{
LIST_ENTRY Entry;
HANDLE hMixer;
ULONG NotificationType;
ULONG Value;
}MIXER_EVENT, *PMIXER_EVENT;
typedef struct
{
HANDLE Handle;
@ -44,60 +36,6 @@ typedef struct
LIST_ENTRY MixerEventList;
}WDMAUD_CLIENT, *PWDMAUD_CLIENT;
typedef struct
{
LIST_ENTRY Entry;
ULONG dwControlID;
}MIXERCONTROL_DATA, *LPMIXERCONTROL_DATA;
typedef struct
{
MIXERCONTROL_DATA Header;
LONG SignedMinimum;
LONG SignedMaximum;
LONG SteppingDelta;
ULONG InputSteppingDelta;
ULONG ValuesCount;
PLONG Values;
}MIXERVOLUME_DATA, *LPMIXERVOLUME_DATA;
typedef struct
{
LIST_ENTRY Entry;
ULONG PinId;
ULONG DeviceIndex;
MIXERLINEW Line;
LPMIXERCONTROLW LineControls;
PULONG NodeIds;
LIST_ENTRY LineControlsExtraData;
}MIXERLINE_EXT, *LPMIXERLINE_EXT;
typedef struct
{
MIXERCAPSW MixCaps;
ULONG DeviceIndex;
LIST_ENTRY LineList;
ULONG ControlId;
}MIXER_INFO, *LPMIXER_INFO;
typedef struct
{
LIST_ENTRY Entry;
ULONG FilterId;
ULONG PinId;
ULONG bInput;
union
{
WAVEOUTCAPSW OutCaps;
WAVEINCAPSW InCaps;
}u;
}WAVE_INFO, *LPWAVE_INFO;
typedef struct
{
LIST_ENTRY Entry;
@ -117,18 +55,17 @@ typedef struct
HANDLE hSysAudio;
PFILE_OBJECT FileObject;
ULONG MixerInfoCount;
LPMIXER_INFO MixerInfo;
ULONG WaveInDeviceCount;
LIST_ENTRY WaveInList;
ULONG WaveOutDeviceCount;
LIST_ENTRY WaveOutList;
LIST_ENTRY WdmAudClientList;
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
typedef struct
{
PWDMAUD_CLIENT ClientInfo;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
SOUND_DEVICE_TYPE DeviceType;
}PIN_CREATE_CONTEXT, *PPIN_CREATE_CONTEXT;
NTSTATUS
NTAPI
OpenWavePin(
@ -279,7 +216,7 @@ NTAPI
WdmAudWaveInitialize(
IN PDEVICE_OBJECT DeviceObject);
NTSTATUS
ULONG
ClosePin(
IN PWDMAUD_CLIENT ClientInfo,
IN ULONG FilterId,
@ -295,18 +232,51 @@ InsertPinHandle(
IN HANDLE PinHandle,
IN ULONG FreeIndex);
NTSTATUS
GetWaveInfoByIndexAndType(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG DeviceIndex,
IN SOUND_DEVICE_TYPE DeviceType,
OUT LPWAVE_INFO *OutWaveInfo);
NTSTATUS
GetSysAudioDevicePnpName(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG DeviceIndex,
OUT LPWSTR * Device);
NTSTATUS
OpenSysAudioDeviceByIndex(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG DeviceIndex,
IN PHANDLE DeviceHandle,
IN PFILE_OBJECT * FileObject);
NTSTATUS
OpenDevice(
IN LPWSTR Device,
OUT PHANDLE DeviceHandle,
OUT PFILE_OBJECT * FileObject);
ULONG
WdmAudGetMixerDeviceCount();
ULONG
WdmAudGetWaveInDeviceCount();
ULONG
WdmAudGetWaveOutDeviceCount();
NTSTATUS
WdmAudGetMixerPnpNameByIndex(
IN ULONG DeviceIndex,
OUT LPWSTR * Device);
NTSTATUS
WdmAudGetPnpNameByIndexAndType(
IN ULONG DeviceIndex,
IN SOUND_DEVICE_TYPE DeviceType,
OUT LPWSTR *Device);
/* sup.c */
ULONG
GetSysAudioDeviceCount(
IN PDEVICE_OBJECT DeviceObject);
#endif

View file

@ -2,17 +2,20 @@
<!DOCTYPE module SYSTEM "../../../../../tools/rbuild/project.dtd">
<module name="wdmaud_kernel" type="kernelmodedriver" installbase="system32/drivers" installname="wdmaud.sys">
<include base="wdmaud_kernel">.</include>
<define name="_COMDDK_" />
<include base="mmixer">.</include>
<include base="ReactOS">include/reactos/libs/sound</include>
<define name="_COMDDK_" />
<library>mmixer</library>
<library>ntoskrnl</library>
<library>rtl</library>
<library>libcntpr</library>
<library>ks</library>
<library>pseh</library>
<library>hal</library>
<file>control.c</file>
<file>deviface.c</file>
<file>entry.c</file>
<file>mixer.c</file>
<file>wave.c</file>
<file>mmixer.c</file>
<file>sup.c</file>
<file>wdmaud.rc</file>
</module>

View file

@ -75,6 +75,15 @@ typedef PVOID (*PMIXER_ALLOC_EVENT_DATA)(
typedef VOID (*PMIXER_FREE_EVENT_DATA)(
IN PVOID EventData);
typedef MIXER_STATUS (*PIN_CREATE_CALLBACK)(
IN PVOID Context,
IN ULONG DeviceId,
IN ULONG PinId,
IN HANDLE hFilter,
IN PKSPIN_CONNECT PinConnect,
IN ACCESS_MASK DesiredAccess,
OUT PHANDLE PinHandle);
typedef struct
{
ULONG SizeOfStruct;
@ -172,6 +181,8 @@ MMixerOpenWave(
IN ULONG DeviceIndex,
IN ULONG bWaveIn,
IN LPWAVEFORMATEX WaveFormat,
IN PIN_CREATE_CALLBACK CreateCallback,
IN PVOID Context,
OUT PHANDLE PinHandle);
MIXER_STATUS

View file

@ -588,7 +588,7 @@ MMixerGetDataByDeviceName(
while(Entry != &MixerList->MixerData)
{
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
if (wcsicmp(DeviceName, MixerData->DeviceName) == 0)
if (wcsicmp(&DeviceName[2], &MixerData->DeviceName[2]) == 0)
{
// found entry
return MixerData;

View file

@ -233,12 +233,15 @@ MMixerOpenWavePin(
IN ULONG PinId,
IN LPWAVEFORMATEX WaveFormatEx,
IN ACCESS_MASK DesiredAccess,
IN PIN_CREATE_CALLBACK CreateCallback,
IN PVOID Context,
OUT PHANDLE PinHandle)
{
PKSPIN_CONNECT PinConnect;
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
LPMIXER_DATA MixerData;
NTSTATUS Status;
MIXER_STATUS MixerStatus;
MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId);
if (!MixerData)
@ -260,16 +263,28 @@ MMixerOpenWavePin(
/* initialize with requested wave format */
MMixerInitializeDataFormat(DataFormat, WaveFormatEx);
/* now create the pin */
Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
if (CreateCallback)
{
/* let the callback handle the creation */
MixerStatus = CreateCallback(Context, DeviceId, PinId, MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
}
else
{
/* now create the pin */
Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
/* normalize status */
if (Status == STATUS_SUCCESS)
MixerStatus = MM_STATUS_SUCCESS;
else
MixerStatus = MM_STATUS_UNSUCCESSFUL;
}
/* free create info */
MixerContext->Free(PinConnect);
if (Status == STATUS_SUCCESS)
return MM_STATUS_SUCCESS;
else
return MM_STATUS_UNSUCCESSFUL;
/* done */
return MixerStatus;
}
VOID
@ -415,6 +430,8 @@ MMixerOpenWave(
IN ULONG DeviceIndex,
IN ULONG bWaveIn,
IN LPWAVEFORMATEX WaveFormat,
IN PIN_CREATE_CALLBACK CreateCallback,
IN PVOID Context,
OUT PHANDLE PinHandle)
{
PMIXER_LIST MixerList;
@ -459,7 +476,7 @@ MMixerOpenWave(
}
/* now try open the pin */
return MMixerOpenWavePin(MixerContext, MixerList, WaveInfo->DeviceId, WaveInfo->PinId, WaveFormat, DesiredAccess, PinHandle);
return MMixerOpenWavePin(MixerContext, MixerList, WaveInfo->DeviceId, WaveInfo->PinId, WaveFormat, DesiredAccess, CreateCallback, Context, PinHandle);
}
MIXER_STATUS