[MMIXER]
[reactos.git] / reactos / lib / drivers / sound / mmixer / controls.c
index 631a82e..5252a7b 100644 (file)
@@ -96,6 +96,12 @@ MMixerGetControlsFromPinByConnectionIndex(
     else
         NodeIndex = CurConnection->ToNode;
 
+    if (NodeIndex > NodeTypes->Count)
+    {
+        // reached end of pin connection
+        return MM_STATUS_SUCCESS;
+    }
+
     /* get target node type of current connection */
     NodeType = MMixerGetNodeType(NodeTypes, NodeIndex);
 
@@ -124,7 +130,7 @@ MMixerGetControlsFromPinByConnectionIndex(
         Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE, TRUE, &NodeConnectionCount, &NodeConnection);
     }
 
-    if (Status != MM_STATUS_SUCCESS)
+    if (Status == MM_STATUS_SUCCESS)
     {
         for(Index = 0; Index < NodeConnectionCount; Index++)
         {
@@ -332,6 +338,7 @@ MMixerAddMixerSourceLine(
     LPWSTR PinName;
     GUID NodeType;
     ULONG BytesReturned, ControlCount, Index;
+    LPGUID Node;
     PULONG Nodes;
 
     if (!bTargetPin)
@@ -414,8 +421,14 @@ MMixerAddMixerSourceLine(
     {
         if (Nodes[Index])
         {
-            // found a node
-            ControlCount++;
+            // get node type
+            Node = MMixerGetNodeType(NodeTypes, Index);
+
+            if (MMixerGetControlTypeFromTopologyNode(Node))
+            {
+                // found a node which can be resolved to a type
+                ControlCount++;
+            }
         }
     }
 
@@ -457,14 +470,20 @@ MMixerAddMixerSourceLine(
         {
             if (Nodes[Index])
             {
-                /* store the node index for retrieving / setting details */
-                SrcLine->NodeIds[ControlCount] = Index;
+                // get node type
+                Node = MMixerGetNodeType(NodeTypes, Index);
 
-                Status = MMixerAddMixerControl(MixerContext, MixerInfo, hDevice, NodeTypes, Index, SrcLine, &SrcLine->LineControls[ControlCount]);
-                if (Status == MM_STATUS_SUCCESS)
+                if (MMixerGetControlTypeFromTopologyNode(Node))
                 {
-                    /* increment control count on success */
-                    ControlCount++;
+                    /* store the node index for retrieving / setting details */
+                    SrcLine->NodeIds[ControlCount] = Index;
+
+                    Status = MMixerAddMixerControl(MixerContext, MixerInfo, hDevice, NodeTypes, Index, SrcLine, &SrcLine->LineControls[ControlCount]);
+                    if (Status == MM_STATUS_SUCCESS)
+                    {
+                        /* increment control count on success */
+                        ControlCount++;
+                    }
                 }
             }
         }
@@ -534,7 +553,8 @@ MIXER_STATUS
 MMixerCreateDestinationLine(
     IN PMIXER_CONTEXT MixerContext,
     IN LPMIXER_INFO MixerInfo,
-    IN ULONG bInputMixer)
+    IN ULONG bInputMixer,
+    IN LPWSTR LineName)
 {
     LPMIXERLINE_EXT DestinationLine;
 
@@ -554,8 +574,19 @@ MMixerCreateDestinationLine(
     DestinationLine->Line.dwUser = 0;
     DestinationLine->Line.dwComponentType = (bInputMixer == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
     DestinationLine->Line.cChannels = 2; //FIXME
-    wcscpy(DestinationLine->Line.szShortName, L"Summe"); //FIXME
-    wcscpy(DestinationLine->Line.szName, L"Summe"); //FIXME
+
+    if (LineName)
+    {
+        wcscpy(DestinationLine->Line.szShortName, LineName);
+        wcscpy(DestinationLine->Line.szName, LineName);
+    }
+    else
+    {
+        /* FIXME no name was found for pin */
+        wcscpy(DestinationLine->Line.szShortName, L"Summe");
+        wcscpy(DestinationLine->Line.szName, L"Summe");
+    }
+
     DestinationLine->Line.Target.dwType = (bInputMixer == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
     DestinationLine->Line.Target.dwDeviceID = !bInputMixer;
     DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
@@ -636,6 +667,7 @@ MMixerAddMixerSourceLines(
 MIXER_STATUS
 MMixerHandlePhysicalConnection(
     IN PMIXER_CONTEXT MixerContext,
+    IN PMIXER_LIST MixerList,
     IN OUT LPMIXER_INFO MixerInfo,
     IN ULONG bInput,
     IN PKSPIN_PHYSICALCONNECTION OutConnection)
@@ -643,47 +675,41 @@ MMixerHandlePhysicalConnection(
     PULONG PinsRef = NULL, PinConnectionIndex = NULL, PinsSrcRef;
     ULONG PinsRefCount, Index, PinConnectionIndexCount;
     MIXER_STATUS Status;
-    HANDLE hDevice = NULL;
     PKSMULTIPLE_ITEM NodeTypes = NULL;
     PKSMULTIPLE_ITEM NodeConnections = NULL;
     PULONG MixerControls;
     ULONG MixerControlsCount;
+    LPMIXER_DATA MixerData;
 
 
     // open the connected filter
-    Status = MixerContext->Open(OutConnection->SymbolicLinkName, &hDevice);
-    if (Status != MM_STATUS_SUCCESS)
-    {
-        DPRINT("OpenDevice failed with %x\n", Status);
-        return Status;
-    }
+    OutConnection->SymbolicLinkName[1] = L'\\';
+    MixerData = MMixerGetDataByDeviceName(MixerList, OutConnection->SymbolicLinkName);
+    ASSERT(MixerData);
 
     // get connected filter pin count
-    PinsRefCount = MMixerGetFilterPinCount(MixerContext, hDevice);
+    PinsRefCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice);
     ASSERT(PinsRefCount);
 
     PinsRef = (PULONG)MixerContext->Alloc(sizeof(ULONG) * PinsRefCount);
     if (!PinsRef)
     {
         // no memory
-        MixerContext->Close(hDevice);
         return MM_STATUS_UNSUCCESSFUL;
     }
 
     // get topology node types
-    Status = MMixerGetFilterTopologyProperty(MixerContext, hDevice, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
+    Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
     if (Status != MM_STATUS_SUCCESS)
     {
-        MixerContext->Close(hDevice);
         MixerContext->Free(PinsRef);
         return Status;
     }
 
     // get topology connections
-    Status = MMixerGetFilterTopologyProperty(MixerContext, hDevice, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
+    Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
     if (Status != MM_STATUS_SUCCESS)
     {
-        MixerContext->Close(hDevice);
         MixerContext->Free(PinsRef);
         MixerContext->Free(NodeTypes);
         return Status;
@@ -694,7 +720,6 @@ MMixerHandlePhysicalConnection(
     Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, OutConnection->Pin, FALSE, !bInput, &PinConnectionIndexCount, &PinConnectionIndex);
     if (Status != MM_STATUS_SUCCESS)
     {
-        MixerContext->Close(hDevice);
         MixerContext->Free(PinsRef);
         MixerContext->Free(NodeTypes);
         MixerContext->Free(NodeConnections);
@@ -708,7 +733,6 @@ MMixerHandlePhysicalConnection(
     Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext, NodeConnections, NodeTypes, FALSE, PinConnectionIndex[0], PinsRef);
     if (Status != MM_STATUS_SUCCESS)
     {
-        MixerContext->Close(hDevice);
         MixerContext->Free(PinsRef);
         MixerContext->Free(NodeTypes);
         MixerContext->Free(NodeConnections);
@@ -736,7 +760,6 @@ MMixerHandlePhysicalConnection(
             if (!PinsSrcRef)
             {
                 /* no memory */
-                MixerContext->Close(hDevice);
                 MixerContext->Free(PinsRef);
                 MixerContext->Free(NodeTypes);
                 MixerContext->Free(NodeConnections);
@@ -750,7 +773,6 @@ MMixerHandlePhysicalConnection(
             if (Status != MM_STATUS_SUCCESS)
             {
                 // failed */
-                MixerContext->Close(hDevice);
                 MixerContext->Free(PinsRef);
                 MixerContext->Free(NodeTypes);
                 MixerContext->Free(NodeConnections);
@@ -769,7 +791,7 @@ MMixerHandlePhysicalConnection(
             }
             PinsSrcRef[OutConnection->Pin] = TRUE;
 
-            Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, hDevice, NodeConnections, NodeTypes, PinsRefCount, OutConnection->Pin, Index, PinsSrcRef);
+            Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, NodeConnections, NodeTypes, PinsRefCount, OutConnection->Pin, Index, PinsSrcRef);
 
             MixerContext->Free(MixerControls);
             MixerContext->Free(PinsSrcRef);
@@ -784,8 +806,7 @@ MIXER_STATUS
 MMixerInitializeFilter(
     IN PMIXER_CONTEXT MixerContext,
     IN PMIXER_LIST MixerList,
-    IN HANDLE hMixer,
-    IN LPWSTR DeviceName,
+    IN LPMIXER_DATA MixerData,
     IN PKSMULTIPLE_ITEM NodeTypes,
     IN PKSMULTIPLE_ITEM NodeConnections,
     IN ULONG PinCount,
@@ -798,6 +819,9 @@ MMixerInitializeFilter(
     ULONG Index;
     ULONG * Pins;
     ULONG bUsed;
+    ULONG BytesReturned;
+    KSP_PIN Pin;
+    LPWSTR Buffer = NULL;
 
     // allocate a mixer info struct
     MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
@@ -813,22 +837,14 @@ MMixerInitializeFilter(
     MixerInfo->MixCaps.vDriverVersion = 1; //FIXME
     MixerInfo->MixCaps.fdwSupport = 0;
     MixerInfo->MixCaps.cDestinations = 1;
-    MixerInfo->hMixer = hMixer;
+    MixerInfo->hMixer = MixerData->hDevice;
+
+    // get mixer name
+    MMixerGetDeviceName(MixerContext, MixerInfo, MixerData->hDeviceInterfaceKey);
 
     // initialize line list
     InitializeListHead(&MixerInfo->LineList);
 
-    /* FIXME find mixer name */
-
-    Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInputMixer);
-    if (Status != MM_STATUS_SUCCESS)
-    {
-        // failed to create destination line
-        MixerContext->Free(MixerInfo);
-        return Status;
-    }
-
-
     // now allocate an array which will receive the indices of the pin 
     // which has a ADC / DAC nodetype in its path
     Pins = (PULONG)MixerContext->Alloc(PinCount * sizeof(ULONG));
@@ -840,6 +856,63 @@ MMixerInitializeFilter(
         return MM_STATUS_NO_MEMORY;
     }
 
+    // now get the target pins of the ADC / DAC node
+    Status = MMixerGetTargetPins(MixerContext, NodeTypes, NodeConnections, NodeIndex, !bInputMixer, Pins, PinCount);
+
+    for(Index = 0; Index < PinCount; Index++)
+    {
+        if (Pins[Index])
+        {
+            /* retrieve pin name */
+            Pin.PinId = Index;
+            Pin.Reserved = 0;
+            Pin.Property.Flags = KSPROPERTY_TYPE_GET;
+            Pin.Property.Set = KSPROPSETID_Pin;
+            Pin.Property.Id = KSPROPERTY_PIN_NAME;
+
+            /* try get pin name size */
+            Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
+
+            if (Status == MM_STATUS_MORE_ENTRIES)
+            {
+                Buffer = (LPWSTR)MixerContext->Alloc(BytesReturned);
+                if (Buffer)
+                {
+                    /* try get pin name */
+                    Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Buffer, BytesReturned, &BytesReturned);
+                    if (Status != MM_STATUS_SUCCESS)
+                    {
+                        MixerContext->Free((PVOID)Buffer);
+                        Buffer = NULL;
+                    }
+                    else
+                    {
+                        // found name, done
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInputMixer, Buffer);
+
+    if (Buffer)
+    {
+        // free name
+        MixerContext->Free(Buffer);
+    }
+
+    if (Status != MM_STATUS_SUCCESS)
+    {
+        // failed to create destination line
+        MixerContext->Free(MixerInfo);
+        MixerContext->Free(Pins);
+
+        return Status;
+    }
+
+    RtlZeroMemory(Pins, sizeof(ULONG) * PinCount);
     // now get the target pins of the ADC / DAC node
     Status = MMixerGetTargetPins(MixerContext, NodeTypes, NodeConnections, NodeIndex, bInputMixer, Pins, PinCount);
 
@@ -863,15 +936,21 @@ MMixerInitializeFilter(
         if (Pins[Index])
         {
             // check if the pin has a physical connection
-            Status = MMixerGetPhysicalConnection(MixerContext, hMixer, Index, &OutConnection);
+            Status = MMixerGetPhysicalConnection(MixerContext, MixerData->hDevice, Index, &OutConnection);
             if (Status == MM_STATUS_SUCCESS)
             {
                 // the pin has a physical connection
-                Status = MMixerHandlePhysicalConnection(MixerContext, MixerInfo, bInputMixer, OutConnection);
+                Status = MMixerHandlePhysicalConnection(MixerContext, MixerList, MixerInfo, bInputMixer, OutConnection);
                 DPRINT("MMixerHandlePhysicalConnection status %u\n", Status);
                 MixerContext->Free(OutConnection);
                 bUsed = TRUE;
             }
+            else
+            {
+                // filter exposes the topology on the same filter
+                MMixerAddMixerSourceLine(MixerContext, MixerInfo, MixerData->hDevice, NodeConnections, NodeTypes, Index, FALSE, FALSE);
+                bUsed = TRUE;
+            }
         }
     }
     MixerContext->Free(Pins);
@@ -879,14 +958,22 @@ MMixerInitializeFilter(
     if (bUsed)
     {
         // store mixer info in list
-        InsertTailList(&MixerList->MixerList, &MixerInfo->Entry);
+        if (!bInputMixer && MixerList->MixerListCount == 1)
+        {
+            //FIXME preferred device should be inserted at front
+            //windows always inserts output mixer in front
+            InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry);
+        }
+        else
+        {
+            InsertTailList(&MixerList->MixerList, &MixerInfo->Entry);
+        }
         MixerList->MixerListCount++;
         DPRINT("New MixerCount %lu\n", MixerList->MixerListCount);
     }
     else
     {
-        // TODO:
-        // filter exposes its topology on the same filter
+        // failed to create a mixer topology
         MMixerFreeMixerInfo(MixerContext, MixerInfo);
     }
 
@@ -898,9 +985,8 @@ MIXER_STATUS
 MMixerSetupFilter(
     IN PMIXER_CONTEXT MixerContext,
     IN PMIXER_LIST MixerList,
-    IN HANDLE hMixer,
-    IN PULONG DeviceCount,
-    IN LPWSTR DeviceName)
+    IN LPMIXER_DATA MixerData,
+    IN PULONG DeviceCount)
 {
     PKSMULTIPLE_ITEM NodeTypes, NodeConnections;
     MIXER_STATUS Status;
@@ -908,12 +994,12 @@ MMixerSetupFilter(
     ULONG NodeIndex;
 
     // get number of pins
-    PinCount = MMixerGetFilterPinCount(MixerContext, hMixer);
+    PinCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice);
     ASSERT(PinCount);
     DPRINT("NumOfPins: %lu\n", PinCount);
 
     // get filter node types
-    Status = MMixerGetFilterTopologyProperty(MixerContext, hMixer, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
+    Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
     if (Status != MM_STATUS_SUCCESS)
     {
         // failed
@@ -921,7 +1007,7 @@ MMixerSetupFilter(
     }
 
     // get filter node connections
-    Status = MMixerGetFilterTopologyProperty(MixerContext, hMixer, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
+    Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
     if (Status != MM_STATUS_SUCCESS)
     {
         // failed
@@ -934,8 +1020,7 @@ MMixerSetupFilter(
     if (NodeIndex != MAXULONG)
     {
         // it has
-
-        Status = MMixerInitializeFilter(MixerContext, MixerList, hMixer, DeviceName, NodeTypes, NodeConnections, PinCount, NodeIndex, FALSE);
+        Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NodeTypes, NodeConnections, PinCount, NodeIndex, FALSE);
         DPRINT("MMixerInitializeFilter Status %u\n", Status);
         // check for success
         if (Status == MM_STATUS_SUCCESS)
@@ -951,7 +1036,7 @@ MMixerSetupFilter(
     if (NodeIndex != MAXULONG)
     {
         // it has
-        Status = MMixerInitializeFilter(MixerContext, MixerList, hMixer, DeviceName, NodeTypes, NodeConnections, PinCount, NodeIndex, TRUE);
+        Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NodeTypes, NodeConnections, PinCount, NodeIndex, TRUE);
         DPRINT("MMixerInitializeFilter Status %u\n", Status);
         // check for success
         if (Status == MM_STATUS_SUCCESS)