Author: janderwald Date: Mon Oct 5 19:00:59 2009 New Revision: 43305
URL: http://svn.reactos.org/svn/reactos?rev=43305&view=rev Log: - Implement setting / getting volume level
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [iso-8859-1] Mon Oct 5 19:00:59 2009 @@ -50,6 +50,29 @@ return NULL; }
+LPMIXERCONTROL_DATA +GetMixerControlDataById( + PLIST_ENTRY ListHead, + DWORD dwControlId) +{ + PLIST_ENTRY Entry; + LPMIXERCONTROL_DATA Control; + + /* get first entry */ + Entry = ListHead->Flink; + + while(Entry != ListHead) + { + Control = (LPMIXERCONTROL_DATA)CONTAINING_RECORD(Entry, MIXERCONTROL_DATA, Entry); + DPRINT("dwSource %x dwSource %x\n", Control->dwControlID, dwControlId); + if (Control->dwControlID == dwControlId) + return Control; + + Entry = Entry->Flink; + } + return NULL; +} + NTSTATUS GetMixerControlById( LPMIXER_INFO MixerInfo, @@ -101,7 +124,7 @@ while(Entry != &MixerInfo->LineList) { MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry); - DPRINT1("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID); + DPRINT("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID); if (MixerLineSrc->Line.dwLineID == dwLineID) return MixerLineSrc;
@@ -889,6 +912,7 @@ IN PFILE_OBJECT FileObject, IN PKSMULTIPLE_ITEM NodeTypes, IN ULONG NodeIndex, + IN LPMIXERLINE_EXT MixerLine, OUT LPMIXERCONTROLW MixerControl) { LPGUID NodeType; @@ -896,7 +920,6 @@ ULONG BytesReturned; NTSTATUS Status; LPWSTR Name; -
/* initialize mixer control */ MixerControl->cbStruct = sizeof(MIXERCONTROLW); @@ -958,6 +981,77 @@ }
MixerInfo->ControlId++; + + if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) + { + KSNODEPROPERTY_AUDIO_CHANNEL Property; + ULONG Length; + PKSPROPERTY_DESCRIPTION Desc; + PKSPROPERTY_MEMBERSHEADER Members; + PKSPROPERTY_STEPPING_LONG Range; + + Length = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG); + Desc = ExAllocatePool(NonPagedPool, Length); + ASSERT(Desc); + RtlZeroMemory(Desc, Length); + + /* setup the request */ + RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL)); + + Property.NodeProperty.NodeId = NodeIndex; + Property.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; + Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT; + Property.NodeProperty.Property.Set = KSPROPSETID_Audio; + + /* get node volume level info */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), Desc, Length, &BytesReturned); + + if (NT_SUCCESS(Status)) + { + LPMIXERVOLUME_DATA VolumeData; + ULONG Steps, MaxRange, Index; + LONG Value; + + Members = (PKSPROPERTY_MEMBERSHEADER)(Desc + 1); + Range = (PKSPROPERTY_STEPPING_LONG)(Members + 1); //98304 + + DPRINT("NodeIndex %u Range Min %d Max %d Steps %x UMin %x UMax %x\n", NodeIndex, Range->Bounds.SignedMinimum, Range->Bounds.SignedMaximum, Range->SteppingDelta, Range->Bounds.UnsignedMinimum, Range->Bounds.UnsignedMaximum); + + VolumeData = ExAllocatePool(NonPagedPool, sizeof(MIXERVOLUME_DATA)); + if (!VolumeData) + return STATUS_INSUFFICIENT_RESOURCES; + + MaxRange = (abs(Range->Bounds.SignedMinimum) + abs(Range->Bounds.SignedMaximum)); + Steps = MaxRange / Range->SteppingDelta + 1; + + /* store mixer control info there */ + VolumeData->Header.dwControlID = MixerControl->dwControlID; + VolumeData->SignedMaximum = Range->Bounds.SignedMaximum; + VolumeData->SignedMinimum = Range->Bounds.SignedMinimum; + VolumeData->SteppingDelta = Range->SteppingDelta; + VolumeData->ValuesCount = Steps; + VolumeData->InputSteppingDelta = 0x10000 / Steps; + + VolumeData->Values = ExAllocatePool(NonPagedPool, sizeof(LONG) * Steps); + if (!VolumeData->Values) + { + ExFreePool(Desc); + ExFreePool(VolumeData); + + return STATUS_INSUFFICIENT_RESOURCES; + } + + Value = Range->Bounds.SignedMinimum; + for(Index = 0; Index < Steps; Index++) + { + VolumeData->Values[Index] = Value; + Value += Range->SteppingDelta; + } + InsertTailList(&MixerLine->LineControlsExtraData, &VolumeData->Header.Entry); + } + ExFreePool(Desc); + } +
DPRINT("Status %x Name %S\n", Status, MixerControl->szName); return STATUS_SUCCESS; @@ -1026,6 +1120,7 @@ SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid; SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid; SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; + InitializeListHead(&SrcLine->LineControlsExtraData); wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
} @@ -1107,7 +1202,7 @@ /* store the node index for retrieving / setting details */ SrcLine->NodeIds[ControlCount] = Index;
- Status = AddMixerControl(MixerInfo, FileObject, NodeTypes, Index, &SrcLine->LineControls[ControlCount]); + Status = AddMixerControl(MixerInfo, FileObject, NodeTypes, Index, SrcLine, &SrcLine->LineControls[ControlCount]); if (NT_SUCCESS(Status)) { /* increment control count on success */ @@ -1430,6 +1525,7 @@
/* initialize source line list */ InitializeListHead(&MixerInfo->LineList); + InitializeListHead(&DestinationLine->LineControlsExtraData);
/* insert destination line */ InsertHeadList(&MixerInfo->LineList, &DestinationLine->Entry); @@ -1781,13 +1877,14 @@ Index = 0; for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++) { + DPRINT1("dwControlType %x\n", MixerLineSrc->LineControls[Index].dwControlType); if (DeviceInfo->u.MixControls.dwControlType == MixerLineSrc->LineControls[Index].dwControlType) { RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW)); return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } } - DPRINT1("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x\n", DeviceInfo->u.MixControls.dwControlType, DeviceInfo->u.MixControls.dwLineID); + DPRINT1("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", DeviceInfo->u.MixControls.dwControlType, DeviceInfo->u.MixControls.dwLineID, MixerLineSrc->Line.cControls); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); }
@@ -1795,6 +1892,65 @@ //DbgBreakPoint(); return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
+} + +NTSTATUS +SetGetControlDetails( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DeviceId, + IN ULONG NodeId, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN ULONG bSet, + IN ULONG PropertyId, + IN ULONG Channel, + IN PLONG InputValue) +{ + KSNODEPROPERTY_AUDIO_CHANNEL Property; + NTSTATUS Status; + HANDLE hDevice; + PFILE_OBJECT FileObject; + LONG Value; + ULONG BytesReturned; + + if (bSet) + Value = *InputValue; + + /* open virtual audio device */ + Status = OpenSysAudioDeviceByIndex(DeviceObject, DeviceId, &hDevice, &FileObject); + + if (!NT_SUCCESS(Status)) + { + /* failed */ + return Status; + } + + /* setup the request */ + RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL)); + + Property.NodeProperty.NodeId = NodeId; + Property.NodeProperty.Property.Id = PropertyId; + Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY; + Property.NodeProperty.Property.Set = KSPROPSETID_Audio; + Property.Channel = Channel; + + if (bSet) + Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_SET; + else + Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_GET; + + /* send the request */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Value, sizeof(LONG), &BytesReturned); + + ObDereferenceObject(FileObject); + ZwClose(hDevice); + + if (!bSet) + { + *InputValue = Value; + } + + DPRINT1("Status %x bSet %u NodeId %u Value %d PropertyId %u\n", Status, bSet, NodeId, Value, PropertyId); + return Status; }
NTSTATUS @@ -1805,13 +1961,9 @@ IN PWDMAUD_DEVICE_INFO DeviceInfo, IN ULONG bSet) { - KSNODEPROPERTY_AUDIO_CHANNEL Property; + LPMIXERCONTROLDETAILS_BOOLEAN Input; + LONG Value; NTSTATUS Status; - HANDLE hDevice; - PFILE_OBJECT FileObject; - BOOL Value; - ULONG BytesReturned; - LPMIXERCONTROLDETAILS_BOOLEAN Input;
if (DeviceInfo->u.MixDetails.cbDetails != sizeof(MIXERCONTROLDETAILS_BOOLEAN)) return STATUS_INVALID_PARAMETER; @@ -1819,49 +1971,87 @@ /* get input */ Input = (LPMIXERCONTROLDETAILS_BOOLEAN)DeviceInfo->u.MixDetails.paDetails;
- - // - // FIXME SEH!!! - // + /* FIXME SEH */ if (bSet) Value = Input->fValue;
- /* open virtual audio device */ - Status = OpenSysAudioDeviceByIndex(DeviceObject, DeviceId, &hDevice, &FileObject); - - if (!NT_SUCCESS(Status)) - { - /* failed */ - return Status; - } - - /* setup the request */ - RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL)); - - Property.NodeProperty.NodeId = NodeId; - Property.NodeProperty.Property.Id = KSPROPERTY_AUDIO_MUTE; - Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY; - Property.NodeProperty.Property.Set = KSPROPSETID_Audio; - Property.Channel = MAXULONG; + /* set control details */ + Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_MUTE, MAXULONG, &Value); + + /* FIXME SEH */ + if (!bSet) + Input->fValue = Value; + + return Status; +} + +NTSTATUS +SetGetVolumeControlDetails( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DeviceId, + IN ULONG NodeId, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN ULONG bSet, + LPMIXERCONTROLW MixerControl, + LPMIXERLINE_EXT MixerLine) +{ + LPMIXERCONTROLDETAILS_UNSIGNED Input; + LONG Value, Index, Channel = 0; + NTSTATUS Status; + LPMIXERVOLUME_DATA VolumeData; + + if (DeviceInfo->u.MixDetails.cbDetails != sizeof(MIXERCONTROLDETAILS_SIGNED)) + return STATUS_INVALID_PARAMETER; + + VolumeData = (LPMIXERVOLUME_DATA)GetMixerControlDataById(&MixerLine->LineControlsExtraData, MixerControl->dwControlID); + if (!VolumeData) + return STATUS_INSUFFICIENT_RESOURCES; + + + /* get input */ + Input = (LPMIXERCONTROLDETAILS_UNSIGNED)DeviceInfo->u.MixDetails.paDetails;
if (bSet) - Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_SET; + { + /* FIXME SEH */ + Value = Input->dwValue; + Index = Value / VolumeData->InputSteppingDelta; + + if (Index >= VolumeData->ValuesCount) + { + DPRINT1("Index %u out of bounds %u \n", Index, VolumeData->ValuesCount); + DbgBreakPoint(); + return STATUS_INVALID_PARAMETER; + } + + Value = VolumeData->Values[Index]; + } + + /* set control details */ + if (bSet) + { + Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value); + Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value); + } else - Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_GET; - - /* send the request */ - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Value, sizeof(BOOL), &BytesReturned); - - ObDereferenceObject(FileObject); - ZwClose(hDevice); + { + Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value); + }
if (!bSet) { - // FIXME SEH !!! - Input->fValue = Value; - } - - DPRINT("Status %x bSet %u NodeId %u Value %u\n", Status, bSet, NodeId, Value); + for(Index = 0; Index < VolumeData->ValuesCount; Index++) + { + if (VolumeData->Values[Index] < Value) + { + /* FIXME SEH */ + Input->dwValue = VolumeData->InputSteppingDelta * Index; + return Status; + } + } + Input->dwValue = VolumeData->InputSteppingDelta * (VolumeData->ValuesCount-1); + } + return Status; }
@@ -1879,7 +2069,7 @@ PWDMAUD_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status;
- DPRINT1("cbStruct %u Expected %u dwControlID %u cChannels %u cMultipleItems %u cbDetails %u paDetails %p Flags %x\n", + DPRINT("cbStruct %u Expected %u dwControlID %u cChannels %u cMultipleItems %u cbDetails %u paDetails %p Flags %x\n", DeviceInfo->u.MixDetails.cbStruct, sizeof(MIXERCONTROLDETAILS), DeviceInfo->u.MixDetails.dwControlID, DeviceInfo->u.MixDetails.cChannels, DeviceInfo->u.MixDetails.cMultipleItems, DeviceInfo->u.MixDetails.cbDetails, DeviceInfo->u.MixDetails.paDetails, DeviceInfo->Flags);
if (DeviceInfo->Flags & MIXER_GETCONTROLDETAILSF_LISTTEXT) @@ -1901,12 +2091,16 @@ }
Status = STATUS_NOT_IMPLEMENTED; + DPRINT("dwLineId %x dwControlID %x dwControlType %x\n", MixerLine->Line.dwLineID, MixerControl->dwControlID, MixerControl->dwControlType); if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) { /* send the request */ Status = SetGetMuteControlDetails(DeviceObject, MixerLine->DeviceIndex, NodeId, DeviceInfo, TRUE); } - + else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) + { + Status = SetGetVolumeControlDetails(DeviceObject, MixerLine->DeviceIndex, NodeId, DeviceInfo, TRUE, MixerControl, MixerLine); + } return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
} @@ -1925,7 +2119,7 @@ PWDMAUD_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status;
- DPRINT1("cbStruct %u Expected %u dwControlID %u cChannels %u cMultipleItems %u cbDetails %u paDetails %p Flags %x\n", + DPRINT("cbStruct %u Expected %u dwControlID %u cChannels %u cMultipleItems %u cbDetails %u paDetails %p Flags %x\n", DeviceInfo->u.MixDetails.cbStruct, sizeof(MIXERCONTROLDETAILS), DeviceInfo->u.MixDetails.dwControlID, DeviceInfo->u.MixDetails.cChannels, DeviceInfo->u.MixDetails.cMultipleItems, DeviceInfo->u.MixDetails.cbDetails, DeviceInfo->u.MixDetails.paDetails, DeviceInfo->Flags);
if (DeviceInfo->Flags & MIXER_GETCONTROLDETAILSF_LISTTEXT) @@ -1952,6 +2146,10 @@ /* send the request */ Status = SetGetMuteControlDetails(DeviceObject, MixerLine->DeviceIndex, NodeId, DeviceInfo, FALSE); } + else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) + { + Status = SetGetVolumeControlDetails(DeviceObject, MixerLine->DeviceIndex, NodeId, DeviceInfo, FALSE, MixerControl, MixerLine); + }
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] Mon Oct 5 19:00:59 2009 @@ -36,11 +36,31 @@ 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;