From 91b69c9d1d685d138a10dd7610298d6fe1665087 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Wed, 9 Dec 2009 16:00:28 +0000 Subject: [PATCH] [MMIXER] - Implement MMixerGetLineInfo, MMixerGetLineControls, MMixerSetControlDetails, MMixerGetControlDetails, MMixerOpen - MMixer library is now ready for testing svn path=/trunk/; revision=44482 --- reactos/lib/drivers/sound/mmixer/controls.c | 8 +- reactos/lib/drivers/sound/mmixer/filter.c | 45 ++++ reactos/lib/drivers/sound/mmixer/mixer.c | 235 +++++++++++++++++++- reactos/lib/drivers/sound/mmixer/mmixer.h | 7 + reactos/lib/drivers/sound/mmixer/priv.h | 41 ++++ reactos/lib/drivers/sound/mmixer/sup.c | 209 +++++++++++++++++ 6 files changed, 538 insertions(+), 7 deletions(-) diff --git a/reactos/lib/drivers/sound/mmixer/controls.c b/reactos/lib/drivers/sound/mmixer/controls.c index 5788a434838..62e0ade8423 100644 --- a/reactos/lib/drivers/sound/mmixer/controls.c +++ b/reactos/lib/drivers/sound/mmixer/controls.c @@ -203,10 +203,10 @@ MMixerAddMixerControl( Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned); if (Status != MM_STATUS_SUCCESS) { - RtlMoveMemory(MixerControl->szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); + MixerContext->Copy(MixerControl->szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); MixerControl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; - RtlMoveMemory(MixerControl->szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); + MixerContext->Copy(MixerControl->szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); MixerControl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; } @@ -512,10 +512,10 @@ MMixerAddMixerSourceLine( if (Status != MM_STATUS_SUCCESS) { - RtlMoveMemory(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR)); + MixerContext->Copy(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR)); SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; - RtlMoveMemory(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR)); + MixerContext->Copy(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR)); SrcLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; } MixerContext->Free(PinName); diff --git a/reactos/lib/drivers/sound/mmixer/filter.c b/reactos/lib/drivers/sound/mmixer/filter.c index 64e19d14b01..b576a4cf650 100644 --- a/reactos/lib/drivers/sound/mmixer/filter.c +++ b/reactos/lib/drivers/sound/mmixer/filter.c @@ -205,3 +205,48 @@ MMixerGetControlTypeFromTopologyNode( UNIMPLEMENTED return 0; } + +MIXER_STATUS +MMixerSetGetControlDetails( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE hMixer, + IN ULONG NodeId, + IN ULONG bSet, + IN ULONG PropertyId, + IN ULONG Channel, + IN PLONG InputValue) +{ + KSNODEPROPERTY_AUDIO_CHANNEL Property; + MIXER_STATUS Status; + LONG Value; + ULONG BytesReturned; + + if (bSet) + Value = *InputValue; + + /* 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; + Property.Reserved = 0; + + if (bSet) + Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_SET; + else + Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_GET; + + /* send the request */ + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Value, sizeof(LONG), &BytesReturned); + + if (!bSet && Status == MM_STATUS_SUCCESS) + { + *InputValue = Value; + } + + DPRINT("Status %x bSet %u NodeId %u Value %d PropertyId %u\n", Status, bSet, NodeId, Value, PropertyId); + return Status; +} diff --git a/reactos/lib/drivers/sound/mmixer/mixer.c b/reactos/lib/drivers/sound/mmixer/mixer.c index 279551aa11f..303e043fef0 100644 --- a/reactos/lib/drivers/sound/mmixer/mixer.c +++ b/reactos/lib/drivers/sound/mmixer/mixer.c @@ -73,11 +73,13 @@ MMixerGetCapabilities( MIXER_STATUS MMixerOpen( IN PMIXER_CONTEXT MixerContext, + IN ULONG MixerId, IN PVOID MixerEvent, IN PMIXER_EVENT MixerEventRoutine, OUT PHANDLE MixerHandle) { MIXER_STATUS Status; + LPMIXER_INFO MixerInfo; // verify mixer context Status = MMixerVerifyContext(MixerContext); @@ -88,7 +90,20 @@ MMixerOpen( return Status; } - return MM_STATUS_NOT_IMPLEMENTED; + MixerInfo = (LPMIXER_INFO)MMixerGetMixerInfoByIndex(MixerContext, MixerId); + if (!MixerInfo) + { + // invalid mixer id + return MM_STATUS_INVALID_PARAMETER; + } + + // FIXME + // handle event notification + + // store result + *MixerHandle = (HANDLE)MixerInfo; + + return MM_STATUS_SUCCESS; } MIXER_STATUS @@ -99,6 +114,8 @@ MMixerGetLineInfo( OUT LPMIXERLINEW MixerLine) { MIXER_STATUS Status; + LPMIXER_INFO MixerInfo; + LPMIXERLINE_EXT MixerLineSrc; // verify mixer context Status = MMixerVerifyContext(MixerContext); @@ -108,6 +125,88 @@ MMixerGetLineInfo( // invalid context passed return Status; } + + // clear hmixer from flags + Flags &=~MIXER_OBJECTF_HMIXER; + + if (Flags == MIXER_GETLINEINFOF_DESTINATION) + { + // cast to mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + if (MixerLine->dwDestination != 0) + { + // destination line member must be zero + return MM_STATUS_INVALID_PARAMETER; + } + + MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE); + ASSERT(MixerLineSrc); + MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); + + return MM_STATUS_SUCCESS; + } + else if (Flags == MIXER_GETLINEINFOF_SOURCE) + { + // cast to mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + + MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE); + ASSERT(MixerLineSrc); + + if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections) + { + DPRINT1("dwSource %u > Destinations %u\n", MixerLine->dwSource, MixerLineSrc->Line.cConnections); + + // invalid parameter + return MM_STATUS_INVALID_PARAMETER; + } + + MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwSource); + if (MixerLineSrc) + { + DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName); + MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); + return MM_STATUS_SUCCESS; + } + return MM_STATUS_UNSUCCESSFUL; + } + else if (Flags == MIXER_GETLINEINFOF_LINEID) + { + // cast to mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID); + if (!MixerLineSrc) + { + // invalid parameter + return MM_STATUS_INVALID_PARAMETER; + } + + /* copy cached data */ + MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); + return MM_STATUS_SUCCESS; + } + else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE) + { + // cast to mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType); + if (!MixerLineSrc) + { + DPRINT1("Failed to find component type %x\n", MixerLine->dwComponentType); + return MM_STATUS_UNSUCCESSFUL; + } + + ASSERT(MixerLineSrc); + + /* copy cached data */ + MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); + return MM_STATUS_SUCCESS; + } + return MM_STATUS_NOT_IMPLEMENTED; } @@ -118,7 +217,11 @@ MMixerGetLineControls( IN ULONG Flags, OUT LPMIXERLINECONTROLS MixerLineControls) { + LPMIXER_INFO MixerInfo; + LPMIXERLINE_EXT MixerLineSrc; + LPMIXERCONTROLW MixerControl; MIXER_STATUS Status; + ULONG Index; // verify mixer context Status = MMixerVerifyContext(MixerContext); @@ -129,6 +232,73 @@ MMixerGetLineControls( return Status; } + Flags &= ~MIXER_OBJECTF_HMIXER; + + if (Flags == MIXER_GETLINECONTROLSF_ALL) + { + // cast to mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID); + + if (!MixerLineSrc) + { + // invalid line id + return MM_STATUS_INVALID_PARAMETER; + } + // copy line control(s) + MixerContext->Copy(MixerLineControls->pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, MixerLineControls->cControls) * sizeof(MIXERCONTROLW)); + + return MM_STATUS_SUCCESS; + } + else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE) + { + // cast to mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID); + + if (!MixerLineSrc) + { + // invalid line id + return MM_STATUS_INVALID_PARAMETER; + } + + ASSERT(MixerLineSrc); + + Index = 0; + for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++) + { + DPRINT("dwControlType %x\n", MixerLineSrc->LineControls[Index].dwControlType); + if (MixerLineControls->dwControlType == MixerLineSrc->LineControls[Index].dwControlType) + { + // found a control with that type + MixerContext->Copy(MixerLineControls->pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW)); + return MM_STATUS_SUCCESS; + } + } + DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls); + return MM_STATUS_UNSUCCESSFUL; + } + else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID) + { + // cast to mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + Status = MMixerGetMixerControlById(MixerInfo, MixerLineControls->dwControlID, NULL, &MixerControl, NULL); + + if (Status != MM_STATUS_SUCCESS) + { + // invalid parameter + return MM_STATUS_INVALID_PARAMETER; + } + + // copy the controls + MixerContext->Copy(MixerLineControls->pamxctrl, MixerControl, sizeof(MIXERCONTROLW)); + return MM_STATUS_SUCCESS; + } + + return MM_STATUS_NOT_IMPLEMENTED; } @@ -140,6 +310,10 @@ MMixerSetControlDetails( OUT LPMIXERCONTROLDETAILS MixerControlDetails) { MIXER_STATUS Status; + ULONG NodeId; + LPMIXER_INFO MixerInfo; + LPMIXERLINE_EXT MixerLine; + LPMIXERCONTROLW MixerControl; // verify mixer context Status = MMixerVerifyContext(MixerContext); @@ -149,7 +323,33 @@ MMixerSetControlDetails( // invalid context passed return Status; } - return MM_STATUS_NOT_IMPLEMENTED; + + // get mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + // get mixer control + Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId); + + // check for success + if (Status != MM_STATUS_SUCCESS) + { + // failed to find control id + return MM_STATUS_INVALID_PARAMETER; + } + + switch(MixerControl->dwControlType) + { + case MIXERCONTROL_CONTROLTYPE_MUTE: + Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo->hMixer, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, TRUE); + break; + case MIXERCONTROL_CONTROLTYPE_VOLUME: + Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo->hMixer, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine); + break; + default: + Status = MM_STATUS_NOT_IMPLEMENTED; + } + + return Status; } MIXER_STATUS @@ -160,6 +360,10 @@ MMixerGetControlDetails( OUT LPMIXERCONTROLDETAILS MixerControlDetails) { MIXER_STATUS Status; + ULONG NodeId; + LPMIXER_INFO MixerInfo; + LPMIXERLINE_EXT MixerLine; + LPMIXERCONTROLW MixerControl; // verify mixer context Status = MMixerVerifyContext(MixerContext); @@ -170,7 +374,32 @@ MMixerGetControlDetails( return Status; } - return MM_STATUS_NOT_IMPLEMENTED; + // get mixer info + MixerInfo = (LPMIXER_INFO)MixerHandle; + + // get mixer control + Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId); + + // check for success + if (Status != MM_STATUS_SUCCESS) + { + // failed to find control id + return MM_STATUS_INVALID_PARAMETER; + } + + switch(MixerControl->dwControlType) + { + case MIXERCONTROL_CONTROLTYPE_MUTE: + Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo->hMixer, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, FALSE); + break; + case MIXERCONTROL_CONTROLTYPE_VOLUME: + Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo->hMixer, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine); + break; + default: + Status = MM_STATUS_NOT_IMPLEMENTED; + } + + return Status; } MIXER_STATUS diff --git a/reactos/lib/drivers/sound/mmixer/mmixer.h b/reactos/lib/drivers/sound/mmixer/mmixer.h index 3f94eaf0d5f..51d9772657c 100644 --- a/reactos/lib/drivers/sound/mmixer/mmixer.h +++ b/reactos/lib/drivers/sound/mmixer/mmixer.h @@ -47,6 +47,11 @@ typedef MIXER_STATUS(*PMIXER_CLOSE)( typedef VOID (*PMIXER_EVENT)( IN PVOID MixerEvent); +typedef VOID (*PMIXER_COPY)( + IN PVOID Dst, + IN PVOID Src, + IN ULONG Length); + typedef struct { @@ -58,6 +63,7 @@ typedef struct PMIXER_FREE Free; PMIXER_OPEN Open; PMIXER_CLOSE Close; + PMIXER_COPY Copy; }MIXER_CONTEXT, *PMIXER_CONTEXT; MIXER_STATUS @@ -79,6 +85,7 @@ MMixerGetCapabilities( MIXER_STATUS MMixerOpen( IN PMIXER_CONTEXT MixerContext, + IN ULONG MixerId, IN PVOID MixerEvent, IN PMIXER_EVENT MixerEventRoutine, OUT PHANDLE MixerHandle); diff --git a/reactos/lib/drivers/sound/mmixer/priv.h b/reactos/lib/drivers/sound/mmixer/priv.h index 430f509146f..3c6e086d78a 100644 --- a/reactos/lib/drivers/sound/mmixer/priv.h +++ b/reactos/lib/drivers/sound/mmixer/priv.h @@ -164,5 +164,46 @@ MMixerGetMixerInfoByIndex( IN PMIXER_CONTEXT MixerContext, IN ULONG MixerIndex); +LPMIXERLINE_EXT +MMixerGetSourceMixerLineByComponentType( + LPMIXER_INFO MixerInfo, + DWORD dwComponentType); + +MIXER_STATUS +MMixerGetMixerControlById( + LPMIXER_INFO MixerInfo, + DWORD dwControlID, + LPMIXERLINE_EXT *MixerLine, + LPMIXERCONTROLW *MixerControl, + PULONG NodeId); + +MIXER_STATUS +MMixerSetGetMuteControlDetails( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE hMixer, + IN ULONG NodeId, + IN ULONG dwLineID, + IN LPMIXERCONTROLDETAILS MixerControlDetails, + IN ULONG bSet); + +MIXER_STATUS +MMixerSetGetVolumeControlDetails( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE hMixer, + IN ULONG NodeId, + IN ULONG bSet, + LPMIXERCONTROLW MixerControl, + IN LPMIXERCONTROLDETAILS MixerControlDetails, + LPMIXERLINE_EXT MixerLine); + +MIXER_STATUS +MMixerSetGetControlDetails( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE hMixer, + IN ULONG NodeId, + IN ULONG bSet, + IN ULONG PropertyId, + IN ULONG Channel, + IN PLONG InputValue); #endif diff --git a/reactos/lib/drivers/sound/mmixer/sup.c b/reactos/lib/drivers/sound/mmixer/sup.c index b1cd58df857..e2e0d840ea0 100644 --- a/reactos/lib/drivers/sound/mmixer/sup.c +++ b/reactos/lib/drivers/sound/mmixer/sup.c @@ -71,6 +71,28 @@ MMixerGetMixerInfoByIndex( return NULL; } +LPMIXERCONTROL_DATA +MMixerGetMixerControlDataById( + 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; +} LPMIXERLINE_EXT MMixerGetSourceMixerLineByLineId( @@ -314,3 +336,190 @@ MMixerGetTargetPins( return Status; } + +LPMIXERLINE_EXT +MMixerGetSourceMixerLineByComponentType( + LPMIXER_INFO MixerInfo, + DWORD dwComponentType) +{ + PLIST_ENTRY Entry; + LPMIXERLINE_EXT MixerLineSrc; + + /* get first entry */ + Entry = MixerInfo->LineList.Flink; + + while(Entry != &MixerInfo->LineList) + { + MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry); + if (MixerLineSrc->Line.dwComponentType == dwComponentType) + return MixerLineSrc; + + Entry = Entry->Flink; + } + + return NULL; +} + +MIXER_STATUS +MMixerGetMixerControlById( + LPMIXER_INFO MixerInfo, + DWORD dwControlID, + LPMIXERLINE_EXT *MixerLine, + LPMIXERCONTROLW *MixerControl, + PULONG NodeId) +{ + PLIST_ENTRY Entry; + LPMIXERLINE_EXT MixerLineSrc; + ULONG Index; + + /* get first entry */ + Entry = MixerInfo->LineList.Flink; + + while(Entry != &MixerInfo->LineList) + { + MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry); + + for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++) + { + if (MixerLineSrc->LineControls[Index].dwControlID == dwControlID) + { + if (MixerLine) + *MixerLine = MixerLineSrc; + if (MixerControl) + *MixerControl = &MixerLineSrc->LineControls[Index]; + if (NodeId) + *NodeId = MixerLineSrc->NodeIds[Index]; + return MM_STATUS_SUCCESS; + } + } + Entry = Entry->Flink; + } + + return MM_STATUS_UNSUCCESSFUL; +} + +ULONG +MMixerGetVolumeControlIndex( + LPMIXERVOLUME_DATA VolumeData, + LONG Value) +{ + ULONG Index; + + for(Index = 0; Index < VolumeData->ValuesCount; Index++) + { + if (VolumeData->Values[Index] > Value) + { + return VolumeData->InputSteppingDelta * Index; + } + } + return VolumeData->InputSteppingDelta * (VolumeData->ValuesCount-1); +} + +MIXER_STATUS +MMixerSetGetMuteControlDetails( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE hMixer, + IN ULONG NodeId, + IN ULONG dwLineID, + IN LPMIXERCONTROLDETAILS MixerControlDetails, + IN ULONG bSet) +{ + LPMIXERCONTROLDETAILS_BOOLEAN Input; + LONG Value; + MIXER_STATUS Status; + + if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_BOOLEAN)) + return MM_STATUS_INVALID_PARAMETER; + + /* get input */ + Input = (LPMIXERCONTROLDETAILS_BOOLEAN)MixerControlDetails->paDetails; + + /* FIXME SEH */ + if (bSet) + Value = Input->fValue; + + /* set control details */ + Status = MMixerSetGetControlDetails(MixerContext, hMixer, NodeId, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value); + + if (Status != MM_STATUS_SUCCESS) + return Status; + + /* FIXME SEH */ + if (!bSet) + { + Input->fValue = Value; + return Status; + } + else + { + // FIXME notify wdmaud clients MM_MIXM_LINE_CHANGE dwLineID + } + + return Status; +} + +MIXER_STATUS +MMixerSetGetVolumeControlDetails( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE hMixer, + IN ULONG NodeId, + IN ULONG bSet, + LPMIXERCONTROLW MixerControl, + IN LPMIXERCONTROLDETAILS MixerControlDetails, + LPMIXERLINE_EXT MixerLine) +{ + LPMIXERCONTROLDETAILS_UNSIGNED Input; + LONG Value, Index, Channel = 0; + ULONG dwValue; + MIXER_STATUS Status; + LPMIXERVOLUME_DATA VolumeData; + + if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_SIGNED)) + return MM_STATUS_INVALID_PARAMETER; + + VolumeData = (LPMIXERVOLUME_DATA)MMixerGetMixerControlDataById(&MixerLine->LineControlsExtraData, MixerControl->dwControlID); + if (!VolumeData) + return MM_STATUS_UNSUCCESSFUL; + + /* get input */ + Input = (LPMIXERCONTROLDETAILS_UNSIGNED)MixerControlDetails->paDetails; + + if (bSet) + { + /* 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 MM_STATUS_INVALID_PARAMETER; + } + + Value = VolumeData->Values[Index]; + } + + /* set control details */ + if (bSet) + { + Status = MMixerSetGetControlDetails(MixerContext, hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value); + Status = MMixerSetGetControlDetails(MixerContext, hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value); + } + else + { + Status = MMixerSetGetControlDetails(MixerContext, hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value); + } + + if (!bSet) + { + dwValue = MMixerGetVolumeControlIndex(VolumeData, (LONG)Value); + /* FIXME SEH */ + Input->dwValue = dwValue; + } + else + { + /* notify clients of a line change MM_MIXM_CONTROL_CHANGE with MixerControl->dwControlID */ + } + return Status; +} -- 2.17.1