[MMIXER]
[reactos.git] / reactos / lib / drivers / sound / mmixer / sup.c
index a5a9107..7bb46f3 100644 (file)
 
 #include "priv.h"
 
+const GUID KSNODETYPE_SUM = {0xDA441A60L, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_DAC = {0x507AE360L, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_ADC = {0x4D837FE0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_AGC = {0xE88C9BA0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_LOUDNESS = {0x41887440L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_MUTE =     {0x02B223C0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_TONE =     {0x7607E580L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_VOLUME =   {0x3A5ACC00L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_PEAKMETER = {0xa085651e, 0x5f0d, 0x4b36, {0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e}};
+const GUID KSNODETYPE_MUX =       {0x2CEAF780, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_STEREO_WIDE = {0xA9E69800L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_CHORUS =      {0x20173F20L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_REVERB =      {0xEF0328E0L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+const GUID KSNODETYPE_SUPERMIX =    {0xE573ADC0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
+
+const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
+const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
+const GUID KSPROPSETID_General                  = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSPROPSETID_Topology                 = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+
 MIXER_STATUS
 MMixerVerifyContext(
     IN PMIXER_CONTEXT MixerContext)
@@ -17,7 +37,8 @@ MMixerVerifyContext(
     if (MixerContext->SizeOfStruct != sizeof(MIXER_CONTEXT))
         return MM_STATUS_INVALID_PARAMETER;
 
-    if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free)
+    if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open || 
+        !MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey)
         return MM_STATUS_INVALID_PARAMETER;
 
     if (!MixerContext->MixerContext)
@@ -38,6 +59,62 @@ MMixerFreeMixerInfo(
     MixerContext->Free((PVOID)MixerInfo);
 }
 
+LPMIXER_INFO
+MMixerGetMixerInfoByIndex(
+    IN PMIXER_CONTEXT MixerContext,
+    IN ULONG MixerIndex)
+{
+    LPMIXER_INFO MixerInfo;
+    PLIST_ENTRY Entry;
+    PMIXER_LIST MixerList;
+    ULONG Index = 0;
+
+    // get mixer list
+    MixerList = (PMIXER_LIST)MixerContext->MixerContext;
+
+    if (!MixerList->MixerListCount)
+        return NULL;
+
+    Entry = MixerList->MixerList.Flink;
+
+    while(Entry != &MixerList->MixerList)
+    {
+        MixerInfo = (LPMIXER_INFO)CONTAINING_RECORD(Entry, MIXER_INFO, Entry);
+
+        if (Index == MixerIndex)
+            return MixerInfo;
+
+        // move to next mixer entry
+        Index++;
+        Entry = Entry->Flink;
+    }
+
+    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(
     LPMIXER_INFO MixerInfo,
@@ -175,6 +252,13 @@ MMixerGetNodeIndexes(
         Connection++;
     }
 
+    if (!Count)
+    {
+        *NodeReferenceCount = 0;
+        *NodeReference = NULL;
+        return MM_STATUS_SUCCESS;
+    }
+
     ASSERT(Count != 0);
 
     /* now allocate node index array */
@@ -280,3 +364,294 @@ 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)
+    {
+        /* TODO */
+        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;
+}
+
+LPMIXER_DATA
+MMixerGetDataByDeviceId(
+    IN PMIXER_LIST MixerList,
+    IN ULONG DeviceId)
+{
+    PLIST_ENTRY Entry;
+    LPMIXER_DATA MixerData;
+
+    Entry = MixerList->MixerData.Flink;
+    while(Entry != &MixerList->MixerData)
+    {
+        MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
+        if (MixerData->DeviceId == DeviceId)
+        {
+            return MixerData;
+        }
+        Entry = Entry->Flink;
+    }
+    return NULL;
+}
+
+LPMIXER_DATA
+MMixerGetDataByDeviceName(
+    IN PMIXER_LIST MixerList,
+    IN LPWSTR DeviceName)
+{
+    PLIST_ENTRY Entry;
+    LPMIXER_DATA MixerData;
+
+    Entry = MixerList->MixerData.Flink;
+    while(Entry != &MixerList->MixerData)
+    {
+        MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
+        if (wcsicmp(DeviceName, MixerData->DeviceName) == 0)
+        {
+            // found entry
+            return MixerData;
+        }
+        Entry = Entry->Flink;
+    }
+    return NULL;
+}
+
+MIXER_STATUS
+MMixerCreateMixerData(
+    IN PMIXER_CONTEXT MixerContext,
+    IN PMIXER_LIST MixerList,
+    IN ULONG DeviceId,
+    IN LPWSTR DeviceName,
+    IN HANDLE hDevice,
+    IN HANDLE hKey)
+{
+    LPMIXER_DATA MixerData;
+
+    MixerData = (LPMIXER_DATA)MixerContext->Alloc(sizeof(MIXER_DATA));
+    if (!MixerData)
+        return MM_STATUS_NO_MEMORY;
+
+    MixerData->DeviceId = DeviceId;
+    MixerData->DeviceName = DeviceName;
+    MixerData->hDevice = hDevice;
+    MixerData->hDeviceInterfaceKey = hKey;
+
+    InsertTailList(&MixerList->MixerData, &MixerData->Entry);
+    MixerList->MixerDataCount++;
+    return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerGetDeviceName(
+    IN PMIXER_CONTEXT MixerContext,
+    IN LPMIXER_INFO MixerInfo,
+    IN HANDLE hKey)
+{
+    LPWSTR Name;
+    HANDLE hTemp;
+    ULONG Length;
+    ULONG Type;
+    MIXER_STATUS Status;
+
+    Status = MixerContext->QueryKeyValue(hKey, L"FriendlyName", (PVOID*)&Name, &Length, &Type);
+    if (Status == MM_STATUS_SUCCESS)
+    {
+        wcscpy(MixerInfo->MixCaps.szPname, Name);
+        MixerContext->Free(Name);
+        return Status;
+    }
+
+    Status = MixerContext->OpenKey(hKey, L"Device Parameters", KEY_READ, &hTemp);
+    if (Status != MM_STATUS_SUCCESS)
+        return Status;
+
+    Status = MixerContext->QueryKeyValue(hKey, L"FriendlyName", (PVOID*)&Name, &Length, &Type);
+    if (Status == MM_STATUS_SUCCESS)
+    {
+        wcscpy(MixerInfo->MixCaps.szPname, Name);
+        MixerContext->Free(Name);
+    }
+
+    MixerContext->CloseKey(hTemp);
+    return Status;
+}