Author: janderwald Date: Wed Dec 9 17:00:28 2009 New Revision: 44482
URL: http://svn.reactos.org/svn/reactos?rev=44482&view=rev Log: [MMIXER] - Implement MMixerGetLineInfo, MMixerGetLineControls, MMixerSetControlDetails, MMixerGetControlDetails, MMixerOpen - MMixer library is now ready for testing
Modified: trunk/reactos/lib/drivers/sound/mmixer/controls.c trunk/reactos/lib/drivers/sound/mmixer/filter.c trunk/reactos/lib/drivers/sound/mmixer/mixer.c trunk/reactos/lib/drivers/sound/mmixer/mmixer.h trunk/reactos/lib/drivers/sound/mmixer/priv.h trunk/reactos/lib/drivers/sound/mmixer/sup.c
Modified: trunk/reactos/lib/drivers/sound/mmixer/controls.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/co... ============================================================================== --- trunk/reactos/lib/drivers/sound/mmixer/controls.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/sound/mmixer/controls.c [iso-8859-1] Wed Dec 9 17:00:28 2009 @@ -203,10 +203,10 @@ 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 @@
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);
Modified: trunk/reactos/lib/drivers/sound/mmixer/filter.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/fi... ============================================================================== --- trunk/reactos/lib/drivers/sound/mmixer/filter.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/sound/mmixer/filter.c [iso-8859-1] Wed Dec 9 17:00:28 2009 @@ -205,3 +205,48 @@ 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; +}
Modified: trunk/reactos/lib/drivers/sound/mmixer/mixer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/mi... ============================================================================== --- trunk/reactos/lib/drivers/sound/mmixer/mixer.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/sound/mmixer/mixer.c [iso-8859-1] Wed Dec 9 17:00:28 2009 @@ -73,22 +73,37 @@ MIXER_STATUS MMixerOpen( IN PMIXER_CONTEXT MixerContext, + IN ULONG MixerId, IN PVOID MixerEvent, IN PMIXER_EVENT MixerEventRoutine, OUT PHANDLE MixerHandle) { MIXER_STATUS Status; - - // verify mixer context - Status = MMixerVerifyContext(MixerContext); - - if (Status != MM_STATUS_SUCCESS) - { - // invalid context passed - return Status; - } - - return MM_STATUS_NOT_IMPLEMENTED; + LPMIXER_INFO MixerInfo; + + // verify mixer context + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + // invalid context passed + return Status; + } + + 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,15 +114,99 @@ OUT LPMIXERLINEW MixerLine) { MIXER_STATUS Status; - - // verify mixer context - Status = MMixerVerifyContext(MixerContext); - - if (Status != MM_STATUS_SUCCESS) - { - // invalid context passed - return Status; - } + LPMIXER_INFO MixerInfo; + LPMIXERLINE_EXT MixerLineSrc; + + // verify mixer context + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + // 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,16 +217,87 @@ IN ULONG Flags, OUT LPMIXERLINECONTROLS MixerLineControls) { - MIXER_STATUS Status; - - // verify mixer context - Status = MMixerVerifyContext(MixerContext); - - if (Status != MM_STATUS_SUCCESS) - { - // invalid context passed - return Status; - } + LPMIXER_INFO MixerInfo; + LPMIXERLINE_EXT MixerLineSrc; + LPMIXERCONTROLW MixerControl; + MIXER_STATUS Status; + ULONG Index; + + // verify mixer context + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + // invalid context passed + 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,16 +310,46 @@ OUT LPMIXERCONTROLDETAILS MixerControlDetails) { MIXER_STATUS Status; - - // verify mixer context - Status = MMixerVerifyContext(MixerContext); - - if (Status != MM_STATUS_SUCCESS) - { - // invalid context passed - return Status; - } - return MM_STATUS_NOT_IMPLEMENTED; + ULONG NodeId; + LPMIXER_INFO MixerInfo; + LPMIXERLINE_EXT MixerLine; + LPMIXERCONTROLW MixerControl; + + // verify mixer context + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + // invalid context passed + return Status; + } + + // 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,17 +360,46 @@ OUT LPMIXERCONTROLDETAILS MixerControlDetails) { MIXER_STATUS Status; - - // verify mixer context - Status = MMixerVerifyContext(MixerContext); - - if (Status != MM_STATUS_SUCCESS) - { - // invalid context passed - return Status; - } - - return MM_STATUS_NOT_IMPLEMENTED; + ULONG NodeId; + LPMIXER_INFO MixerInfo; + LPMIXERLINE_EXT MixerLine; + LPMIXERCONTROLW MixerControl; + + // verify mixer context + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + // invalid context passed + return Status; + } + + // 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
Modified: trunk/reactos/lib/drivers/sound/mmixer/mmixer.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/mm... ============================================================================== --- trunk/reactos/lib/drivers/sound/mmixer/mmixer.h [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/sound/mmixer/mmixer.h [iso-8859-1] Wed Dec 9 17:00:28 2009 @@ -47,6 +47,11 @@ 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 @@ PMIXER_FREE Free; PMIXER_OPEN Open; PMIXER_CLOSE Close; + PMIXER_COPY Copy; }MIXER_CONTEXT, *PMIXER_CONTEXT;
MIXER_STATUS @@ -79,6 +85,7 @@ MIXER_STATUS MMixerOpen( IN PMIXER_CONTEXT MixerContext, + IN ULONG MixerId, IN PVOID MixerEvent, IN PMIXER_EVENT MixerEventRoutine, OUT PHANDLE MixerHandle);
Modified: trunk/reactos/lib/drivers/sound/mmixer/priv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/pr... ============================================================================== --- trunk/reactos/lib/drivers/sound/mmixer/priv.h [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/sound/mmixer/priv.h [iso-8859-1] Wed Dec 9 17:00:28 2009 @@ -164,5 +164,46 @@ 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
Modified: trunk/reactos/lib/drivers/sound/mmixer/sup.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/su... ============================================================================== --- trunk/reactos/lib/drivers/sound/mmixer/sup.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/sound/mmixer/sup.c [iso-8859-1] Wed Dec 9 17:00:28 2009 @@ -71,6 +71,28 @@ 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 @@
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; +}