[AUDIO-BRINGUP]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 4 Dec 2010 17:45:48 +0000 (17:45 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 4 Dec 2010 17:45:48 +0000 (17:45 +0000)
- More fixes for mmixer library
- Store destination lines sharing the same mixer object in the same object
- Fix generating destination lines id / soure lines
- Add mux node for input mixers
- Disable code which checked if the topology node has already been reserved for an another line. Tests in WinXP concluded that ms does not do this at all, though documentation claims it
- Add source line to the correct destination line
- Fix a memory leak
- Fix tons of bugs in MMixerGetLineInfo

svn path=/branches/audio-bringup/; revision=49949

dll/win32/wdmaud.drv/mmixer.c
lib/drivers/sound/mmixer/controls.c
lib/drivers/sound/mmixer/mixer.c
lib/drivers/sound/mmixer/topology.c

index 764c33b..54457c4 100644 (file)
@@ -121,7 +121,7 @@ Free(PVOID Block)
 VOID
 Copy(PVOID Src, PVOID Dst, ULONG NumBytes)
 {
-    CopyMemory(Src, Dst, NumBytes);
+    RtlMoveMemory(Src, Dst, NumBytes);
 }
 
 MIXER_STATUS
index 5b5dd18..2406c5d 100644 (file)
@@ -202,9 +202,10 @@ MMixerCreateDestinationLine(
     /* initialize mixer destination line */
     DestinationLine->Line.cbStruct = sizeof(MIXERLINEW);
     DestinationLine->Line.dwSource = MAXULONG;
-    DestinationLine->Line.dwLineID = DESTINATION_LINE;
+    DestinationLine->Line.dwLineID = MixerInfo->MixCaps.cDestinations + DESTINATION_LINE;
     DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE;
     DestinationLine->Line.dwUser = 0;
+    DestinationLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations;
     DestinationLine->Line.dwComponentType = (bInputMixer == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
     DestinationLine->Line.cChannels = 2; /* FIXME */
 
@@ -219,7 +220,7 @@ MMixerCreateDestinationLine(
     }
 
     DestinationLine->Line.Target.dwType = (bInputMixer == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
-    DestinationLine->Line.Target.dwDeviceID = !bInputMixer;
+    DestinationLine->Line.Target.dwDeviceID = 0; //FIXME
     DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
     DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
     DestinationLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
@@ -231,7 +232,10 @@ MMixerCreateDestinationLine(
     InitializeListHead(&DestinationLine->LineControlsExtraData);
 
     /* insert into mixer info */
-    InsertHeadList(&MixerInfo->LineList, &DestinationLine->Entry);
+    InsertTailList(&MixerInfo->LineList, &DestinationLine->Entry);
+
+    /* increment destination count */
+    MixerInfo->MixCaps.cDestinations++;
 
     /* done */
     return MM_STATUS_SUCCESS;
@@ -385,6 +389,7 @@ MMixerCountMixerControls(
     IN PMIXER_CONTEXT MixerContext,
     IN PTOPOLOGY Topology,
     IN ULONG PinId,
+    IN ULONG bInputMixer,
     IN ULONG bUpStream,
     OUT PULONG OutNodesCount,
     OUT PULONG OutNodes,
@@ -424,6 +429,12 @@ MMixerCountMixerControls(
         if (bTerminator)
         {
             /* found terminator */
+            if (bInputMixer)
+            {
+                /* add mux source for source destination line */
+                OutNodes[Count] = NodeIndex;
+                Count++;
+            }
             break;
         }
 
@@ -489,13 +500,13 @@ MMixerAddMixerControlsToMixerLineByNodeIndexArray(
     {
         /* check if the node has already been reserved to a line */
         MMixerIsTopologyNodeReserved(Topology, Nodes[Index], &bReserved);
-
+#if 0 /* MS lies */
         if (bReserved)
         {
             /* node is already used, skip it */
             continue;
         }
-
+#endif
         /* set node status as used */
         MMixerSetTopologyNodeReserved(Topology, Nodes[Index]);
 
@@ -524,6 +535,7 @@ MMixerBuildMixerSourceLine(
     IN ULONG PinId,
     IN ULONG NodesCount,
     IN PULONG Nodes,
+    IN ULONG DestinationLineID,
     OUT LPMIXERLINE_EXT * OutSrcLine)
 {
     LPMIXERLINE_EXT SrcLine, DstLine;
@@ -540,7 +552,7 @@ MMixerBuildMixerSourceLine(
     }
 
     /* get destination line */
-    DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
+    DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
     ASSERT(DstLine);
 
     /* initialize mixer src line */
@@ -552,7 +564,7 @@ MMixerBuildMixerSourceLine(
     SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
     SrcLine->Line.dwDestination = 0;
     SrcLine->Line.dwSource = DstLine->Line.cConnections;
-    SrcLine->Line.dwLineID = (DstLine->Line.cConnections * 0x10000);
+    SrcLine->Line.dwLineID = (DstLine->Line.cConnections * 0x10000)+ (MixerInfo->MixCaps.cDestinations-1);
     SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE;
     SrcLine->Line.dwUser = 0;
     SrcLine->Line.cChannels = DstLine->Line.cChannels;
@@ -603,6 +615,7 @@ MMixerAddMixerSourceLines(
     IN PMIXER_CONTEXT MixerContext,
     IN OUT LPMIXER_INFO MixerInfo,
     IN PTOPOLOGY Topology,
+    IN ULONG DestinationLineID,
     IN ULONG LineTerminator)
 {
     PULONG AllNodes, AllPins, AllPinNodes;
@@ -612,7 +625,7 @@ MMixerAddMixerSourceLines(
     LPMIXERLINE_EXT DstLine, SrcLine;
 
     /* get destination line */
-    DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
+    DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
     ASSERT(DstLine);
 
     /* allocate an array to store all nodes which are upstream of the line terminator */
@@ -647,9 +660,9 @@ MMixerAddMixerSourceLines(
     AllPinsCount = 0;
     MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllPinsCount, AllPins);
 
-    DPRINT("LineTerminator %lu\n", LineTerminator);
-    DPRINT("PinCount %lu\n", AllPinsCount);
-    DPRINT("AllNodesCount %lu\n", AllNodesCount);
+    DPRINT1("LineTerminator %lu\n", LineTerminator);
+    DPRINT1("PinCount %lu\n", AllPinsCount);
+    DPRINT1("AllNodesCount %lu\n", AllNodesCount);
 
     /* now construct the source lines which are attached to the destination line */
     Index = AllPinsCount;
@@ -693,8 +706,11 @@ MMixerAddMixerSourceLines(
 
         if (AllPinNodesCount)
         {
+#ifdef MMIXER_DEBUG
+            ULONG TempIndex;
+#endif
             /* now build the mixer source line */
-            Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, Topology, PinId, AllPinNodesCount, AllPinNodes, &SrcLine);
+            Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, Topology, PinId, AllPinNodesCount, AllPinNodes, DestinationLineID, &SrcLine);
 
              if (Status == MM_STATUS_SUCCESS)
              {
@@ -703,8 +719,19 @@ MMixerAddMixerSourceLines(
 
                  /* increment destination line count */
                  DstLine->Line.cConnections++;
+#ifdef MMIXER_DEBUG
+                 DPRINT1("Adding PinId %lu AllPinNodesCount %lu to DestinationLine %lu\n", PinId, AllPinNodesCount, DestinationLineID);
+                 for(TempIndex = 0; TempIndex < AllPinNodesCount; TempIndex++)
+                     DPRINT1("NodeIndex %lu\n", AllPinNodes[TempIndex]);
+#endif
              }
         }
+        else
+        {
+#ifdef MMIXER_DEBUG
+            DPRINT1("Discarding DestinationLineID %lu PinId %lu NO NODES!\n", DestinationLineID, PinId);
+#endif
+        }
 
     }while(Index != 0);
 
@@ -719,6 +746,7 @@ MMixerAddMixerControlsToDestinationLine(
     IN PTOPOLOGY Topology,
     IN ULONG PinId,
     IN ULONG bInput,
+    IN ULONG DestinationLineId,
     OUT PULONG OutLineTerminator)
 {
     PULONG Nodes;
@@ -737,7 +765,7 @@ MMixerAddMixerControlsToDestinationLine(
     }
 
     /* get all destination line controls */
-    Status = MMixerCountMixerControls(MixerContext, Topology, PinId, TRUE, &NodesCount, Nodes, &LineTerminator);
+    Status = MMixerCountMixerControls(MixerContext, Topology, PinId, bInput, TRUE, &NodesCount, Nodes, &LineTerminator);
 
     /* check for success */
     if (Status != MM_STATUS_SUCCESS)
@@ -748,7 +776,7 @@ MMixerAddMixerControlsToDestinationLine(
     }
 
     /* get destination mixer line */
-    DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
+    DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineId);
 
     /* sanity check */
     ASSERT(DstLine);
@@ -823,7 +851,7 @@ MMixerHandlePhysicalConnection(
     IN PKSPIN_PHYSICALCONNECTION OutConnection)
 {
     MIXER_STATUS Status;
-    ULONG PinsCount, LineTerminator;
+    ULONG PinsCount, LineTerminator, DestinationLineID;
     PULONG Pins;
     PTOPOLOGY Topology;
 
@@ -838,17 +866,35 @@ MMixerHandlePhysicalConnection(
          return MM_STATUS_UNSUCCESSFUL;
      }
 
-    DPRINT("Name %S, Pin %lu bInput %lu\n", OutConnection->SymbolicLinkName, OutConnection->Pin, bInput);
+    DPRINT1("Name %S, Pin %lu bInput %lu\n", OutConnection->SymbolicLinkName, OutConnection->Pin, bInput);
+
+    if (MixerInfo->hMixer != NULL)
+    {
+         /* dont replace mixer destination handles */
+         DPRINT1("MixerInfo hDevice %p MixerData hDevice %p\n", MixerInfo->hMixer, MixerData->hDevice);
+         ASSERT(MixerInfo->hMixer == MixerData->hDevice);
+    }
 
     /* store connected mixer handle */
     MixerInfo->hMixer = MixerData->hDevice;
 
+    if (MixerData->Topology == NULL)
+    {
+        /* construct new topology */
+        Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
+        if (Status != MM_STATUS_SUCCESS)
+        {
+            /* failed to create topology */
+            return Status;
+        }
 
-    Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
-    if (Status != MM_STATUS_SUCCESS)
+        /* store topology */
+        MixerData->Topology = Topology;
+    }
+    else
     {
-        /* failed to create topology */
-        return Status;
+        /* re-use existing topology */
+        Topology = MixerData->Topology;
     }
 
     /* allocate pin index array which will hold all referenced pins */
@@ -887,79 +933,93 @@ MMixerHandlePhysicalConnection(
         /* create destination line */
         Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, Pins[0], bInput);
 
+        /* calculate destination line id */
+        DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
+
         if (Status != MM_STATUS_SUCCESS)
         {
+            /* failed to build destination line */
             MixerContext->Free(Pins);
-            //MMixerFreeTopology(Topology);
 
             /* return error code */
             return Status;
         }
 
         /* add mixer controls to destination line */
-        Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, Topology, Pins[0], bInput, &LineTerminator);
+        Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, Topology, Pins[0], bInput, DestinationLineID,  &LineTerminator);
 
         if (Status == MM_STATUS_SUCCESS)
         {
             /* now add the rest of the source lines */
-            Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, Topology, LineTerminator);
+            Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, Topology, DestinationLineID, LineTerminator);
         }
     }
     else
     {
-        Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, Topology, OutConnection->Pin, bInput, &LineTerminator);
+        /* calculate destination line id */
+        DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
+
+        /* add mixer controls */
+        Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, Topology, OutConnection->Pin, bInput, DestinationLineID, &LineTerminator);
 
         if (Status == MM_STATUS_SUCCESS)
         {
             /* now add the rest of the source lines */
-            Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, Topology, LineTerminator);
+            Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, Topology, DestinationLineID, LineTerminator);
         }
     }
 
-    /* free topology */
-    //MMixerFreeTopology(Topology);
-
     return Status;
 }
 
-
 MIXER_STATUS
 MMixerInitializeFilter(
     IN PMIXER_CONTEXT MixerContext,
     IN PMIXER_LIST MixerList,
     IN LPMIXER_DATA MixerData,
+    IN LPMIXER_INFO MixerInfo,
     IN PTOPOLOGY Topology,
     IN ULONG NodeIndex,
-    IN ULONG bInputMixer)
+    IN ULONG bInputMixer,
+    IN OUT LPMIXER_INFO * OutMixerInfo)
 {
-    LPMIXER_INFO MixerInfo;
+
     MIXER_STATUS Status;
     PKSPIN_PHYSICALCONNECTION OutConnection;
     ULONG * Pins;
     ULONG PinsFound;
+    ULONG NewMixerInfo = FALSE;
 
-    /* allocate a mixer info struct */
-    MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
-    if (!MixerInfo)
+    if (MixerInfo == NULL)
     {
-        /* no memory */
-        return MM_STATUS_NO_MEMORY;
-    }
+        /* allocate a mixer info struct */
+        MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
+        if (!MixerInfo)
+        {
+            /* no memory */
+            return MM_STATUS_NO_MEMORY;
+        }
 
-    /* intialize mixer caps */
-    MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */
-    MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */
-    MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */
-    MixerInfo->MixCaps.fdwSupport = 0;
-    MixerInfo->MixCaps.cDestinations = 1;
-    MixerInfo->hMixer = MixerData->hDevice;
+        /* new mixer info */
+        NewMixerInfo = TRUE;
+
+        /* intialize mixer caps */
+        MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */
+        MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */
+        MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */
+        MixerInfo->MixCaps.fdwSupport = 0;
+        MixerInfo->MixCaps.cDestinations = 0;
 
-    /* get mixer name */
-    MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey);
+        /* get mixer name */
+        MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey);
+
+        /* initialize line list */
+        InitializeListHead(&MixerInfo->LineList);
+        InitializeListHead(&MixerInfo->EventList);
+    }
 
-    /* initialize line list */
-    InitializeListHead(&MixerInfo->LineList);
-    InitializeListHead(&MixerInfo->EventList);
+    /* store mixer info */
+    *OutMixerInfo = MixerInfo;
 
     /* now allocate an array which will receive the indices of the pin 
      * which has a ADC / DAC nodetype in its path
@@ -977,7 +1037,7 @@ MMixerInitializeFilter(
     PinsFound = 0;
     MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins);
 
-    /* if there is now pin found, we have a broken topology */
+    /* if there is no pin found, we have a broken topology */
     ASSERT(PinsFound != 0);
 
     /* now create a wave info struct */
@@ -1039,26 +1099,19 @@ MMixerInitializeFilter(
          * handle drivers which expose their topology on the same filter
          */
         ASSERT(0);
+        MixerInfo->hMixer = MixerData->hDevice;
     }
 
     /* free pins */
     MixerContext->Free(Pins);
 
-    if (!bInputMixer && MixerList->MixerListCount == 1)
+    if (NewMixerInfo)
     {
-        /* FIXME preferred device should be inserted at front
-         * windows always inserts output mixer in front
-         */
+        /* insert mixer */
         InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry);
+        /* increment mixer count */
+        MixerList->MixerListCount++;
     }
-    else
-    {
-        /* insert at back */
-        InsertTailList(&MixerList->MixerList, &MixerInfo->Entry);
-    }
-
-    /* increment mixer count */
-    MixerList->MixerListCount++;
 
     /* done */
     return Status;
@@ -1074,6 +1127,7 @@ MMixerSetupFilter(
     MIXER_STATUS Status;
     PTOPOLOGY Topology;
     ULONG NodeIndex;
+    LPMIXER_INFO MixerInfo = NULL;
 
     /* check if topology has already been built */
     if (MixerData->Topology == NULL)
@@ -1101,7 +1155,7 @@ MMixerSetupFilter(
     if (NodeIndex != MAXULONG)
     {
         /* it has */
-        Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, Topology, NodeIndex, FALSE);
+        Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NULL, Topology, NodeIndex, FALSE, &MixerInfo);
 
         /* check for success */
         if (Status == MM_STATUS_SUCCESS)
@@ -1109,7 +1163,11 @@ MMixerSetupFilter(
             /* increment mixer count */
             (*DeviceCount)++;
         }
-
+        else
+        {
+            /* reset mixer info in case of error */
+            MixerInfo = NULL;
+        }
     }
 
     /* check if the filter has an wave in node */
@@ -1117,7 +1175,7 @@ MMixerSetupFilter(
     if (NodeIndex != MAXULONG)
     {
         /* it has */
-        Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, Topology, NodeIndex, TRUE);
+        Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, MixerInfo, Topology, NodeIndex, TRUE, &MixerInfo);
 
         /* check for success */
         if (Status == MM_STATUS_SUCCESS)
@@ -1128,6 +1186,8 @@ MMixerSetupFilter(
 
     }
 
+    /* TODO: handle alternative mixer types + apply hacks for Wave source line */
+
     /* activate midi devices */
     MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology);
 
index c216110..f88ac68 100644 (file)
@@ -123,6 +123,7 @@ MMixerGetLineInfo(
     MIXER_STATUS Status;
     LPMIXER_INFO MixerInfo;
     LPMIXERLINE_EXT MixerLineSrc;
+    ULONG DestinationLineID;
 
     /* verify mixer context */
     Status = MMixerVerifyContext(MixerContext);
@@ -144,24 +145,43 @@ MMixerGetLineInfo(
         }
     }
 
+    if (MixerLine->cbStruct != sizeof(MIXERLINEW))
+       {
+               DPRINT1("MixerLine Expected %lu but got %lu\n", sizeof(MIXERLINEW), MixerLine->cbStruct);
+               return MM_STATUS_INVALID_PARAMETER;
+       }
+
+
     /* clear hmixer from flags */
     Flags &=~MIXER_OBJECTF_HMIXER;
 
+    DPRINT1("MMixerGetLineInfo MixerId %lu Flags %lu\n", MixerId, Flags);
+
     if (Flags == MIXER_GETLINEINFOF_DESTINATION)
     {
         /* cast to mixer info */
         MixerInfo = (LPMIXER_INFO)MixerHandle;
 
-        if (MixerLine->dwDestination != 0)
+        /* calculate destination line id */
+        DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
+
+        /* get destination line */
+        MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
+
+        if (MixerLineSrc == NULL)
         {
-            /* destination line member must be zero */
-            return MM_STATUS_INVALID_PARAMETER;
+            DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
+            return MM_STATUS_UNSUCCESSFUL;
         }
-
-        MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
-        ASSERT(MixerLineSrc);
+        /* copy mixer line */
         MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
 
+        /* make sure it is null terminated */
+        MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
+        MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
+        MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
+
+        /* done */
         return MM_STATUS_SUCCESS;
     }
     else if (Flags == MIXER_GETLINEINFOF_SOURCE)
@@ -169,41 +189,71 @@ MMixerGetLineInfo(
         /* cast to mixer info */
         MixerInfo = (LPMIXER_INFO)MixerHandle;
 
+        /* calculate destination line id */
+        DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
 
-        MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
-        ASSERT(MixerLineSrc);
+        /* get destination line */
+        MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
 
-        if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
+        if (MixerLineSrc == NULL)
         {
-            DPRINT("dwSource %u > Destinations %u\n", MixerLine->dwSource, MixerLineSrc->Line.cConnections);
-
-            /* invalid parameter */
-            return MM_STATUS_INVALID_PARAMETER;
+            DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
+            return MM_STATUS_UNSUCCESSFUL;
         }
 
-        MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwSource * 0x10000);
-        if (MixerLineSrc)
+        /* check if dwSource is out of bounds */
+        if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
         {
-            DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
-            MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
-            return MM_STATUS_SUCCESS;
+            DPRINT1("MixerCaps Name %S MixerLineName %S Connections %lu dwSource %lu not found\n", MixerInfo->MixCaps.szPname, MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections, MixerLine->dwSource);
+            return MM_STATUS_UNSUCCESSFUL;
         }
-        return MM_STATUS_UNSUCCESSFUL;
+
+        /* calculate destination line id */
+        DestinationLineID = (MixerLine->dwSource * DESTINATION_LINE) + MixerLine->dwDestination;
+
+        /* get target destination line id */
+        MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
+
+        /* sanity check */
+        ASSERT(MixerLineSrc);
+
+        DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
+
+        /* copy mixer line */
+        MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
+
+        /* make sure it is null terminated */
+        MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
+        MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
+        MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
+
+        /* done */
+        return MM_STATUS_SUCCESS;
     }
     else if (Flags == MIXER_GETLINEINFOF_LINEID)
     {
         /* cast to mixer info */
         MixerInfo = (LPMIXER_INFO)MixerHandle;
 
+        /* try to find line */
         MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
         if (!MixerLineSrc)
         {
             /* invalid parameter */
+            DPRINT1("MixerName %S Line not found %lu\n", MixerInfo->MixCaps.szPname, MixerLine->dwLineID);
             return MM_STATUS_INVALID_PARAMETER;
         }
 
-        /* copy cached data */
+        DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
+
+        /* copy mixer line*/
         MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
+
+        /* make sure it is null terminated */
+        MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
+        MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
+        MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
+
         return MM_STATUS_SUCCESS;
     }
     else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
@@ -211,6 +261,7 @@ MMixerGetLineInfo(
         /* cast to mixer info */
         MixerInfo = (LPMIXER_INFO)MixerHandle;
 
+        /* find mixer line by component type */
         MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
         if (!MixerLineSrc)
         {
@@ -218,12 +269,25 @@ MMixerGetLineInfo(
             return MM_STATUS_UNSUCCESSFUL;
         }
 
-        ASSERT(MixerLineSrc);
-
-        /* copy cached data */
+        /* copy mixer line */
         MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
+
+        /* make sure it is null terminated */
+        MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
+        MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
+        MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
+
+        /* done */
         return MM_STATUS_SUCCESS;
     }
+    else if (Flags == MIXER_GETLINEINFOF_TARGETTYPE)
+    {
+        DPRINT1("MIXER_GETLINEINFOF_TARGETTYPE handling is unimplemented\n");
+    }
+    else
+    {
+        DPRINT1("Unknown Flags %lx handling is unimplemented\n", Flags);
+    }
 
     return MM_STATUS_NOT_IMPLEMENTED;
 }
@@ -459,6 +523,66 @@ MMixerGetControlDetails(
     return Status;
 }
 
+VOID
+MMixerPrintMixers(
+    IN PMIXER_CONTEXT MixerContext,
+    IN PMIXER_LIST MixerList)
+{
+    ULONG Index, SubIndex, DestinationLineID;
+    LPMIXER_INFO MixerInfo;
+    LPMIXERLINE_EXT DstMixerLine;
+
+    DPRINT1("MixerList %p\n", MixerList);
+    DPRINT1("MidiInCount %lu\n", MixerList->MidiInListCount);
+    DPRINT1("MidiOutCount %lu\n", MixerList->MidiOutListCount);
+    DPRINT1("WaveInCount %lu\n", MixerList->WaveInListCount);
+    DPRINT1("WaveOutCount %lu\n", MixerList->WaveOutListCount);
+    DPRINT1("MixerCount %p\n", MixerList->MixerListCount);
+
+
+    for(Index = 0; Index < MixerList->MixerListCount; Index++)
+    {
+        /* get mixer info */
+        MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, Index);
+
+        ASSERT(MixerInfo);
+        DPRINT1("\n");
+        DPRINT1("Name :%S\n", MixerInfo->MixCaps.szPname);
+        DPRINT1("cDestinations: %lu\n", MixerInfo->MixCaps.cDestinations);
+        DPRINT1("fdwSupport %lu\n", MixerInfo->MixCaps.fdwSupport);
+        DPRINT1("vDriverVersion %lx\n", MixerInfo->MixCaps.vDriverVersion);
+        DPRINT1("wMid %lx\n", MixerInfo->MixCaps.wMid);
+        DPRINT1("wPid %lx\n", MixerInfo->MixCaps.wPid);
+
+        for(SubIndex = 0; SubIndex < MixerInfo->MixCaps.cDestinations; SubIndex++)
+        {
+            /* calculate destination line id */
+            DestinationLineID = (SubIndex + DESTINATION_LINE);
+
+            /* get destination line */
+            DstMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
+            DPRINT1("\n");
+            DPRINT1("cChannels %lu\n", DstMixerLine->Line.cChannels);
+            DPRINT1("cConnections %lu\n", DstMixerLine->Line.cConnections);
+            DPRINT1("cControls %lu\n", DstMixerLine->Line.cControls);
+            DPRINT1("dwComponentType %lx\n", DstMixerLine->Line.dwComponentType);
+            DPRINT1("dwDestination %lu\n", DstMixerLine->Line.dwDestination);
+            DPRINT1("dwLineID %lx\n", DstMixerLine->Line.dwLineID);
+            DPRINT1("dwSource %lx\n", DstMixerLine->Line.dwSource);
+            DPRINT1("dwUser %lu\n", DstMixerLine->Line.dwUser);
+            DPRINT1("fdwLine %lu\n", DstMixerLine->Line.fdwLine);
+            DPRINT1("szName %S\n", DstMixerLine->Line.szName);
+            DPRINT1("szShortName %S\n", DstMixerLine->Line.szShortName);
+            DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine->Line.Target.dwDeviceID);
+            DPRINT1("Target.dwType %lu\n", DstMixerLine->Line.Target.dwType);
+            DPRINT1("Target.szName %S\n", DstMixerLine->Line.Target.szPname);
+            DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine->Line.Target.vDriverVersion);
+            DPRINT1("Target.wMid %lx\n", DstMixerLine->Line.Target.wMid );
+            DPRINT1("Target.wPid %lx\n", DstMixerLine->Line.Target.wPid);
+        }
+    }
+}
+
 MIXER_STATUS
 MMixerInitialize(
     IN PMIXER_CONTEXT MixerContext,
@@ -560,6 +684,8 @@ MMixerInitialize(
         Entry = Entry->Flink;
     }
 
+    MMixerPrintMixers(MixerContext, MixerList);
+
     /* done */
     return MM_STATUS_SUCCESS;
 }
index 44e85da..d55cf6c 100644 (file)
@@ -745,16 +745,15 @@ MMixerGetUpOrDownstreamNodes(
         /* node should not have been visited */
         ASSERT(Node->Visited == FALSE);
 
+        /* mark node as visited */
+        TopologyNode->Visited = TRUE;
+
         /* add them to node array */
         MMixerAddPinIndexToArray(MixerContext, Node->NodeIndex, Topology->TopologyNodesCount, OutNodeCount, OutNodes);
 
         /* recursively visit them */
         MMixerGetUpOrDownstreamNodes(MixerContext, Topology, TopologyNodes[Index], bUpStream, OutNodeCount, OutNodes);
     }
-
-    /* mark node as visited */
-    TopologyNode->Visited = TRUE;
-
 }
 
 MIXER_STATUS