Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencontrols.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: lib/drivers/sound/mmixer/controls.c 00005 * PURPOSE: Mixer Control Iteration Functions 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 #include "priv.h" 00010 00011 const GUID KSNODETYPE_DESKTOP_MICROPHONE = {0xDFF21BE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00012 const GUID KSNODETYPE_LEGACY_AUDIO_CONNECTOR = {0xDFF21FE4, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00013 const GUID KSNODETYPE_TELEPHONE = {0xDFF21EE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00014 const GUID KSNODETYPE_PHONE_LINE = {0xDFF21EE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00015 const GUID KSNODETYPE_DOWN_LINE_PHONE = {0xDFF21EE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00016 const GUID KSNODETYPE_DESKTOP_SPEAKER = {0xDFF21CE4, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00017 const GUID KSNODETYPE_ROOM_SPEAKER = {0xDFF21CE5, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00018 const GUID KSNODETYPE_COMMUNICATION_SPEAKER = {0xDFF21CE6, 0xF70F, 0x11D0, {0xB9,0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00019 const GUID KSNODETYPE_HEADPHONES = {0xDFF21CE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00020 const GUID KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO = {0xDFF21CE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00021 const GUID KSNODETYPE_MICROPHONE = {0xDFF21BE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9,0x22, 0x31, 0x96}}; 00022 const GUID KSCATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00023 const GUID KSNODETYPE_SPDIF_INTERFACE = {0xDFF21FE5, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00024 const GUID KSNODETYPE_ANALOG_CONNECTOR = {0xDFF21FE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00025 const GUID KSNODETYPE_SPEAKER = {0xDFF21CE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00026 const GUID KSNODETYPE_CD_PLAYER = {0xDFF220E3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00027 const GUID KSNODETYPE_SYNTHESIZER = {0xDFF220F3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00028 const GUID KSNODETYPE_LINE_CONNECTOR = {0xDFF21FE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0,0xC9, 0x22, 0x31, 0x96}}; 00029 const GUID PINNAME_VIDEO_CAPTURE = {0xfb6c4281, 0x353, 0x11d1, {0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba}}; 00030 00031 MIXER_STATUS 00032 MMixerAddMixerControl( 00033 IN PMIXER_CONTEXT MixerContext, 00034 IN LPMIXER_INFO MixerInfo, 00035 IN HANDLE hMixer, 00036 IN PTOPOLOGY Topology, 00037 IN ULONG NodeIndex, 00038 IN LPMIXERLINE_EXT MixerLine, 00039 IN ULONG MaxChannels) 00040 { 00041 LPGUID NodeType; 00042 KSP_NODE Node; 00043 ULONG BytesReturned; 00044 MIXER_STATUS Status; 00045 LPWSTR Name; 00046 LPMIXERCONTROL_EXT MixerControl; 00047 00048 /* allocate mixer control */ 00049 MixerControl = MixerContext->Alloc(sizeof(MIXERCONTROL_EXT)); 00050 if (!MixerControl) 00051 { 00052 /* no memory */ 00053 return MM_STATUS_NO_MEMORY; 00054 } 00055 00056 00057 /* initialize mixer control */ 00058 MixerControl->hDevice = hMixer; 00059 MixerControl->NodeID = NodeIndex; 00060 MixerControl->ExtraData = NULL; 00061 00062 MixerControl->Control.cbStruct = sizeof(MIXERCONTROLW); 00063 MixerControl->Control.dwControlID = MixerInfo->ControlId; 00064 00065 /* get node type */ 00066 NodeType = MMixerGetNodeTypeFromTopology(Topology, NodeIndex); 00067 /* store control type */ 00068 MixerControl->Control.dwControlType = MMixerGetControlTypeFromTopologyNode(NodeType); 00069 00070 MixerControl->Control.fdwControl = (MaxChannels > 1 ? 0 : MIXERCONTROL_CONTROLF_UNIFORM); 00071 MixerControl->Control.cMultipleItems = 0; 00072 00073 /* setup request to retrieve name */ 00074 Node.NodeId = NodeIndex; 00075 Node.Property.Id = KSPROPERTY_TOPOLOGY_NAME; 00076 Node.Property.Flags = KSPROPERTY_TYPE_GET; 00077 Node.Property.Set = KSPROPSETID_Topology; 00078 Node.Reserved = 0; 00079 00080 /* get node name size */ 00081 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), NULL, 0, &BytesReturned); 00082 00083 if (Status == MM_STATUS_MORE_ENTRIES) 00084 { 00085 ASSERT(BytesReturned != 0); 00086 Name = (LPWSTR)MixerContext->Alloc(BytesReturned); 00087 if (!Name) 00088 { 00089 /* not enough memory */ 00090 return MM_STATUS_NO_MEMORY; 00091 } 00092 00093 /* get node name */ 00094 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned); 00095 00096 if (Status == MM_STATUS_SUCCESS) 00097 { 00098 MixerContext->Copy(MixerControl->Control.szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); 00099 MixerControl->Control.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; 00100 00101 MixerContext->Copy(MixerControl->Control.szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); 00102 MixerControl->Control.szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; 00103 } 00104 00105 /* free name buffer */ 00106 MixerContext->Free(Name); 00107 } 00108 00109 /* increment control count */ 00110 MixerInfo->ControlId++; 00111 00112 /* insert control */ 00113 InsertTailList(&MixerLine->ControlsList, &MixerControl->Entry); 00114 00115 if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_MUX) 00116 { 00117 ULONG NodesCount; 00118 PULONG Nodes; 00119 00120 /* allocate topology nodes array */ 00121 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &Nodes); 00122 00123 if (Status != MM_STATUS_SUCCESS) 00124 { 00125 /* out of memory */ 00126 return STATUS_NO_MEMORY; 00127 } 00128 00129 /* get connected node count */ 00130 MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, TRUE, &NodesCount, Nodes); 00131 00132 /* TODO */ 00133 MixerContext->Free(Nodes); 00134 00135 /* setup mux bounds */ 00136 MixerControl->Control.Bounds.dwMinimum = 0; 00137 MixerControl->Control.Bounds.dwMaximum = NodesCount - 1; 00138 MixerControl->Control.Metrics.dwReserved[0] = NodesCount; 00139 MixerControl->Control.cMultipleItems = NodesCount; 00140 MixerControl->Control.fdwControl |= MIXERCONTROL_CONTROLF_UNIFORM | MIXERCONTROL_CONTROLF_MULTIPLE; 00141 } 00142 else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) 00143 { 00144 MixerControl->Control.Bounds.dwMinimum = 0; 00145 MixerControl->Control.Bounds.dwMaximum = 1; 00146 } 00147 else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_ONOFF) 00148 { 00149 /* only needs to set bounds */ 00150 MixerControl->Control.Bounds.dwMinimum = 0; 00151 MixerControl->Control.Bounds.dwMaximum = 1; 00152 } 00153 else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) 00154 { 00155 KSNODEPROPERTY_AUDIO_CHANNEL Property; 00156 ULONG Length; 00157 PKSPROPERTY_DESCRIPTION Desc; 00158 PKSPROPERTY_MEMBERSHEADER Members; 00159 PKSPROPERTY_STEPPING_LONG Range; 00160 00161 MixerControl->Control.Bounds.dwMinimum = 0; 00162 MixerControl->Control.Bounds.dwMaximum = 0xFFFF; 00163 MixerControl->Control.Metrics.cSteps = 0xC0; /* FIXME */ 00164 00165 Length = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG); 00166 Desc = (PKSPROPERTY_DESCRIPTION)MixerContext->Alloc(Length); 00167 ASSERT(Desc); 00168 00169 /* setup the request */ 00170 RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL)); 00171 00172 Property.NodeProperty.NodeId = NodeIndex; 00173 Property.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; 00174 Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY; 00175 Property.NodeProperty.Property.Set = KSPROPSETID_Audio; 00176 00177 /* get node volume level info */ 00178 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), Desc, Length, &BytesReturned); 00179 00180 if (Status == MM_STATUS_SUCCESS) 00181 { 00182 LPMIXERVOLUME_DATA VolumeData; 00183 ULONG Steps, MaxRange, Index; 00184 LONG Value; 00185 00186 Members = (PKSPROPERTY_MEMBERSHEADER)(Desc + 1); 00187 Range = (PKSPROPERTY_STEPPING_LONG)(Members + 1); 00188 00189 DPRINT("NodeIndex %u Range Min %d Max %d Steps %x UMin %x UMax %x\n", NodeIndex, Range->Bounds.SignedMinimum, Range->Bounds.SignedMaximum, Range->SteppingDelta, Range->Bounds.UnsignedMinimum, Range->Bounds.UnsignedMaximum); 00190 00191 MaxRange = Range->Bounds.UnsignedMaximum - Range->Bounds.UnsignedMinimum; 00192 00193 if (MaxRange) 00194 { 00195 ASSERT(MaxRange); 00196 VolumeData = (LPMIXERVOLUME_DATA)MixerContext->Alloc(sizeof(MIXERVOLUME_DATA)); 00197 if (!VolumeData) 00198 return MM_STATUS_NO_MEMORY; 00199 00200 Steps = MaxRange / Range->SteppingDelta + 1; 00201 00202 /* store mixer control info there */ 00203 VolumeData->Header.dwControlID = MixerControl->Control.dwControlID; 00204 VolumeData->SignedMaximum = Range->Bounds.SignedMaximum; 00205 VolumeData->SignedMinimum = Range->Bounds.SignedMinimum; 00206 VolumeData->SteppingDelta = Range->SteppingDelta; 00207 VolumeData->ValuesCount = Steps; 00208 VolumeData->InputSteppingDelta = 0x10000 / Steps; 00209 00210 VolumeData->Values = (PLONG)MixerContext->Alloc(sizeof(LONG) * Steps); 00211 if (!VolumeData->Values) 00212 { 00213 MixerContext->Free(Desc); 00214 MixerContext->Free(VolumeData); 00215 return MM_STATUS_NO_MEMORY; 00216 } 00217 00218 Value = Range->Bounds.SignedMinimum; 00219 for(Index = 0; Index < Steps; Index++) 00220 { 00221 VolumeData->Values[Index] = Value; 00222 Value += Range->SteppingDelta; 00223 } 00224 MixerControl->ExtraData = VolumeData; 00225 } 00226 } 00227 MixerContext->Free(Desc); 00228 } 00229 00230 DPRINT("Status %x Name %S\n", Status, MixerControl->Control.szName); 00231 return MM_STATUS_SUCCESS; 00232 } 00233 00234 MIXER_STATUS 00235 MMixerCreateDestinationLine( 00236 IN PMIXER_CONTEXT MixerContext, 00237 IN LPMIXER_INFO MixerInfo, 00238 IN ULONG bInputMixer, 00239 IN LPWSTR LineName) 00240 { 00241 LPMIXERLINE_EXT DestinationLine; 00242 00243 /* allocate a mixer destination line */ 00244 DestinationLine = (LPMIXERLINE_EXT) MixerContext->Alloc(sizeof(MIXERLINE_EXT)); 00245 if (!MixerInfo) 00246 { 00247 /* no memory */ 00248 return MM_STATUS_NO_MEMORY; 00249 } 00250 00251 /* initialize mixer destination line */ 00252 DestinationLine->Line.cbStruct = sizeof(MIXERLINEW); 00253 DestinationLine->Line.cChannels = 2; /* FIXME */ 00254 DestinationLine->Line.cConnections = 0; 00255 DestinationLine->Line.cControls = 0; 00256 DestinationLine->Line.dwComponentType = (bInputMixer == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN); 00257 DestinationLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations; 00258 DestinationLine->Line.dwLineID = MixerInfo->MixCaps.cDestinations + DESTINATION_LINE; 00259 DestinationLine->Line.dwSource = MAXULONG; 00260 DestinationLine->Line.dwUser = 0; 00261 DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE; 00262 00263 00264 if (LineName) 00265 { 00266 MixerContext->Copy(DestinationLine->Line.szShortName, LineName, (min(MIXER_SHORT_NAME_CHARS, wcslen(LineName)+1)) * sizeof(WCHAR)); 00267 DestinationLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; 00268 00269 MixerContext->Copy(DestinationLine->Line.szName, LineName, (min(MIXER_LONG_NAME_CHARS, wcslen(LineName)+1)) * sizeof(WCHAR)); 00270 DestinationLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; 00271 00272 } 00273 00274 DestinationLine->Line.Target.dwType = (bInputMixer == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN); 00275 DestinationLine->Line.Target.dwDeviceID = 0; //FIXME 00276 DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid; 00277 DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid; 00278 DestinationLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; 00279 00280 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0); 00281 wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname); 00282 00283 /* initialize extra line */ 00284 InitializeListHead(&DestinationLine->ControlsList); 00285 00286 /* insert into mixer info */ 00287 InsertTailList(&MixerInfo->LineList, &DestinationLine->Entry); 00288 00289 /* increment destination count */ 00290 MixerInfo->MixCaps.cDestinations++; 00291 00292 /* done */ 00293 return MM_STATUS_SUCCESS; 00294 } 00295 00296 MIXER_STATUS 00297 MMixerGetPinName( 00298 IN PMIXER_CONTEXT MixerContext, 00299 IN LPMIXER_INFO MixerInfo, 00300 IN HANDLE hMixer, 00301 IN ULONG PinId, 00302 IN OUT LPWSTR * OutBuffer) 00303 { 00304 KSP_PIN Pin; 00305 ULONG BytesReturned; 00306 LPWSTR Buffer; 00307 MIXER_STATUS Status; 00308 00309 /* prepare pin */ 00310 Pin.PinId = PinId; 00311 Pin.Reserved = 0; 00312 Pin.Property.Flags = KSPROPERTY_TYPE_GET; 00313 Pin.Property.Set = KSPROPSETID_Pin; 00314 Pin.Property.Id = KSPROPERTY_PIN_NAME; 00315 00316 /* try get pin name size */ 00317 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned); 00318 00319 /* check if buffer overflowed */ 00320 if (Status == MM_STATUS_MORE_ENTRIES) 00321 { 00322 /* allocate buffer */ 00323 Buffer = (LPWSTR)MixerContext->Alloc(BytesReturned); 00324 if (!Buffer) 00325 { 00326 /* out of memory */ 00327 return MM_STATUS_NO_MEMORY; 00328 } 00329 00330 /* try get pin name */ 00331 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Buffer, BytesReturned, &BytesReturned); 00332 if (Status != MM_STATUS_SUCCESS) 00333 { 00334 /* failed to get pin name */ 00335 MixerContext->Free((PVOID)Buffer); 00336 return Status; 00337 } 00338 00339 /* successfully obtained pin name */ 00340 *OutBuffer = Buffer; 00341 return MM_STATUS_SUCCESS; 00342 } 00343 00344 /* failed to get pin name */ 00345 return Status; 00346 } 00347 00348 MIXER_STATUS 00349 MMixerBuildMixerDestinationLine( 00350 IN PMIXER_CONTEXT MixerContext, 00351 IN OUT LPMIXER_INFO MixerInfo, 00352 IN HANDLE hMixer, 00353 IN ULONG PinId, 00354 IN ULONG bInput) 00355 { 00356 LPWSTR PinName; 00357 MIXER_STATUS Status; 00358 00359 /* try get pin name */ 00360 Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName); 00361 if (Status == MM_STATUS_SUCCESS) 00362 { 00363 /* create mixer destination line */ 00364 00365 Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, PinName); 00366 00367 /* free pin name */ 00368 MixerContext->Free(PinName); 00369 } 00370 else 00371 { 00372 /* create mixer destination line unlocalized */ 00373 Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, L"No Name"); 00374 } 00375 00376 return Status; 00377 } 00378 00379 MIXER_STATUS 00380 MMixerBuildTopology( 00381 IN PMIXER_CONTEXT MixerContext, 00382 IN LPMIXER_DATA MixerData, 00383 OUT PTOPOLOGY * OutTopology) 00384 { 00385 ULONG PinsCount; 00386 PKSMULTIPLE_ITEM NodeTypes = NULL; 00387 PKSMULTIPLE_ITEM NodeConnections = NULL; 00388 MIXER_STATUS Status; 00389 00390 if (MixerData->Topology) 00391 { 00392 /* re-use existing topology */ 00393 *OutTopology = MixerData->Topology; 00394 00395 return MM_STATUS_SUCCESS; 00396 } 00397 00398 /* get connected filter pin count */ 00399 PinsCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice); 00400 00401 if (!PinsCount) 00402 { 00403 /* referenced filter does not have any pins */ 00404 return MM_STATUS_UNSUCCESSFUL; 00405 } 00406 00407 /* get topology node types */ 00408 Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes); 00409 if (Status != MM_STATUS_SUCCESS) 00410 { 00411 /* failed to get topology node types */ 00412 return Status; 00413 } 00414 00415 /* get topology connections */ 00416 Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections); 00417 if (Status != MM_STATUS_SUCCESS) 00418 { 00419 /* failed to get topology connections */ 00420 MixerContext->Free(NodeTypes); 00421 return Status; 00422 } 00423 00424 /* create a topology */ 00425 Status = MMixerCreateTopology(MixerContext, PinsCount, NodeConnections, NodeTypes, OutTopology); 00426 00427 /* free node types & connections */ 00428 MixerContext->Free(NodeConnections); 00429 MixerContext->Free(NodeTypes); 00430 00431 if (Status == MM_STATUS_SUCCESS) 00432 { 00433 /* store topology object */ 00434 MixerData->Topology = *OutTopology; 00435 } 00436 00437 /* done */ 00438 return Status; 00439 } 00440 00441 MIXER_STATUS 00442 MMixerCountMixerControls( 00443 IN PMIXER_CONTEXT MixerContext, 00444 IN PTOPOLOGY Topology, 00445 IN ULONG PinId, 00446 IN ULONG bInputMixer, 00447 IN ULONG bUpStream, 00448 OUT PULONG OutNodesCount, 00449 OUT PULONG OutNodes, 00450 OUT PULONG OutLineTerminator) 00451 { 00452 PULONG Nodes; 00453 ULONG NodesCount, NodeIndex, Count, bTerminator; 00454 MIXER_STATUS Status; 00455 00456 /* allocate an array to store all nodes which are upstream of this pin */ 00457 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &Nodes); 00458 00459 if (Status != MM_STATUS_SUCCESS) 00460 { 00461 /* out of memory */ 00462 return STATUS_NO_MEMORY; 00463 } 00464 00465 /* mark result array as zero */ 00466 *OutNodesCount = 0; 00467 00468 /* get next nodes */ 00469 MMixerGetNextNodesFromPinIndex(MixerContext, Topology, PinId, bUpStream, &NodesCount, Nodes); 00470 00471 if (NodesCount == 0) 00472 { 00473 /* a pin which is not connected from any node 00474 * a) it is a topology bug (driver bug) 00475 * b) the request is from an alternative mixer 00476 alternative mixer code scans all pins which have not been used and tries to build lines 00477 */ 00478 DPRINT1("MMixerCountMixerControls PinId %lu is not connected by any node\n", PinId); 00479 MMixerPrintTopology(Topology); 00480 return MM_STATUS_UNSUCCESSFUL; 00481 } 00482 00483 /* assume no topology split before getting line terminator */ 00484 ASSERT(NodesCount == 1); 00485 00486 /* get first node */ 00487 NodeIndex = Nodes[0]; 00488 Count = 0; 00489 00490 do 00491 { 00492 /* check if the node is a terminator */ 00493 MMixerIsNodeTerminator(Topology, NodeIndex, &bTerminator); 00494 00495 if (bTerminator) 00496 { 00497 /* found terminator */ 00498 if (bInputMixer) 00499 { 00500 /* add mux source for source destination line */ 00501 OutNodes[Count] = NodeIndex; 00502 Count++; 00503 } 00504 break; 00505 } 00506 00507 /* store node id */ 00508 OutNodes[Count] = NodeIndex; 00509 00510 /* increment node count */ 00511 Count++; 00512 00513 /* get next nodes upstream */ 00514 MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, bUpStream, &NodesCount, Nodes); 00515 00516 /* assume there is a node connected */ 00517 ASSERT(NodesCount != 0); 00518 ASSERT(NodesCount == 1); 00519 00520 /* use first index */ 00521 NodeIndex = Nodes[0]; 00522 00523 }while(TRUE); 00524 00525 /* free node index */ 00526 MixerContext->Free(Nodes); 00527 00528 /* store nodes count */ 00529 *OutNodesCount = Count; 00530 00531 /* store line terminator */ 00532 *OutLineTerminator = NodeIndex; 00533 00534 /* done */ 00535 return MM_STATUS_SUCCESS; 00536 } 00537 00538 MIXER_STATUS 00539 MMixerGetChannelCountEnhanced( 00540 IN PMIXER_CONTEXT MixerContext, 00541 IN LPMIXER_INFO MixerInfo, 00542 IN HANDLE hMixer, 00543 IN ULONG NodeId, 00544 OUT PULONG MaxChannels) 00545 { 00546 KSPROPERTY_DESCRIPTION Description; 00547 PKSPROPERTY_DESCRIPTION NewDescription; 00548 PKSPROPERTY_MEMBERSHEADER Header; 00549 ULONG BytesReturned; 00550 KSP_NODE Request; 00551 MIXER_STATUS Status; 00552 00553 /* try #1 obtain it via description */ 00554 Request.NodeId = NodeId; 00555 Request.Reserved = 0; 00556 Request.Property.Set = KSPROPSETID_Audio; 00557 Request.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY; 00558 Request.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; 00559 00560 00561 /* get description */ 00562 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)&Description, sizeof(KSPROPERTY_DESCRIPTION), &BytesReturned); 00563 if (Status == MM_STATUS_SUCCESS) 00564 { 00565 if (Description.DescriptionSize >= sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) && (Description.MembersListCount > 0)) 00566 { 00567 /* allocate new description */ 00568 NewDescription = MixerContext->Alloc(Description.DescriptionSize); 00569 00570 if (!NewDescription) 00571 { 00572 /* not enough memory */ 00573 return MM_STATUS_NO_MEMORY; 00574 } 00575 00576 /* get description */ 00577 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)NewDescription, Description.DescriptionSize, &BytesReturned); 00578 if (Status == MM_STATUS_SUCCESS) 00579 { 00580 /* get header */ 00581 Header = (PKSPROPERTY_MEMBERSHEADER)(NewDescription + 1); 00582 00583 if (Header->Flags & KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL) 00584 { 00585 /* found enhanced flag */ 00586 ASSERT(Header->MembersCount > 1); 00587 00588 /* store channel count */ 00589 *MaxChannels = Header->MembersCount; 00590 00591 /* free description */ 00592 MixerContext->Free(NewDescription); 00593 00594 /* done */ 00595 return MM_STATUS_SUCCESS; 00596 } 00597 } 00598 00599 /* free description */ 00600 MixerContext->Free(NewDescription); 00601 } 00602 } 00603 00604 /* failed to get channel count enhanced */ 00605 return MM_STATUS_UNSUCCESSFUL; 00606 } 00607 00608 VOID 00609 MMixerGetChannelCountLegacy( 00610 IN PMIXER_CONTEXT MixerContext, 00611 IN LPMIXER_INFO MixerInfo, 00612 IN HANDLE hMixer, 00613 IN ULONG NodeId, 00614 OUT PULONG MaxChannels) 00615 { 00616 ULONG BytesReturned; 00617 MIXER_STATUS Status; 00618 KSNODEPROPERTY_AUDIO_CHANNEL Channel; 00619 LONG Volume; 00620 00621 /* setup request */ 00622 Channel.Reserved = 0; 00623 Channel.NodeProperty.NodeId = NodeId; 00624 Channel.NodeProperty.Reserved = 0; 00625 Channel.NodeProperty.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY; 00626 Channel.NodeProperty.Property.Set = KSPROPSETID_Audio; 00627 Channel.Channel = 0; 00628 Channel.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; 00629 00630 do 00631 { 00632 /* get channel volume */ 00633 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Channel, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Volume, sizeof(LONG), &BytesReturned); 00634 if (Status != MM_STATUS_SUCCESS) 00635 break; 00636 00637 /* increment channel count */ 00638 Channel.Channel++; 00639 00640 }while(TRUE); 00641 00642 /* store channel count */ 00643 *MaxChannels = Channel.Channel; 00644 00645 } 00646 00647 VOID 00648 MMixerGetMaxChannelsForNode( 00649 IN PMIXER_CONTEXT MixerContext, 00650 IN LPMIXER_INFO MixerInfo, 00651 IN HANDLE hMixer, 00652 IN ULONG NodeId, 00653 OUT PULONG MaxChannels) 00654 { 00655 MIXER_STATUS Status; 00656 00657 /* try to get it enhanced */ 00658 Status = MMixerGetChannelCountEnhanced(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels); 00659 00660 if (Status != MM_STATUS_SUCCESS) 00661 { 00662 /* get it old-fashioned way */ 00663 MMixerGetChannelCountLegacy(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels); 00664 } 00665 } 00666 00667 MIXER_STATUS 00668 MMixerAddMixerControlsToMixerLineByNodeIndexArray( 00669 IN PMIXER_CONTEXT MixerContext, 00670 IN LPMIXER_INFO MixerInfo, 00671 IN HANDLE hMixer, 00672 IN PTOPOLOGY Topology, 00673 IN OUT LPMIXERLINE_EXT DstLine, 00674 IN ULONG NodesCount, 00675 IN PULONG Nodes) 00676 { 00677 ULONG Index, Count, bReserved; 00678 MIXER_STATUS Status; 00679 LPGUID NodeType; 00680 ULONG MaxChannels; 00681 00682 /* initialize control count */ 00683 Count = 0; 00684 00685 for(Index = 0; Index < NodesCount; Index++) 00686 { 00687 /* check if the node has already been reserved to a line */ 00688 MMixerIsTopologyNodeReserved(Topology, Nodes[Index], &bReserved); 00689 #if 0 /* MS lies */ 00690 if (bReserved) 00691 { 00692 /* node is already used, skip it */ 00693 continue; 00694 } 00695 #endif 00696 /* set node status as used */ 00697 MMixerSetTopologyNodeReserved(Topology, Nodes[Index]); 00698 00699 /* query node type */ 00700 NodeType = MMixerGetNodeTypeFromTopology(Topology, Nodes[Index]); 00701 00702 if (IsEqualGUIDAligned(NodeType, &KSNODETYPE_VOLUME)) 00703 { 00704 /* calculate maximum channel count for node */ 00705 MMixerGetMaxChannelsForNode(MixerContext, MixerInfo, hMixer, Nodes[Index], &MaxChannels); 00706 00707 DPRINT("NodeId %lu MaxChannels %lu Line %S Id %lu\n", Nodes[Index], MaxChannels, DstLine->Line.szName, DstLine->Line.dwLineID); 00708 /* calculate maximum channels */ 00709 DstLine->Line.cChannels = min(DstLine->Line.cChannels, MaxChannels); 00710 } 00711 else 00712 { 00713 /* use default of one channel */ 00714 MaxChannels = 1; 00715 } 00716 00717 /* now add the mixer control */ 00718 Status = MMixerAddMixerControl(MixerContext, MixerInfo, hMixer, Topology, Nodes[Index], DstLine, MaxChannels); 00719 00720 if (Status == MM_STATUS_SUCCESS) 00721 { 00722 /* increment control count */ 00723 Count++; 00724 } 00725 } 00726 00727 /* store control count */ 00728 DstLine->Line.cControls = Count; 00729 00730 /* done */ 00731 return MM_STATUS_SUCCESS; 00732 } 00733 00734 MIXER_STATUS 00735 MMixerGetComponentAndTargetType( 00736 IN PMIXER_CONTEXT MixerContext, 00737 IN OUT LPMIXER_INFO MixerInfo, 00738 IN HANDLE hMixer, 00739 IN ULONG PinId, 00740 OUT PULONG ComponentType, 00741 OUT PULONG TargetType) 00742 { 00743 KSPIN_DATAFLOW DataFlow; 00744 KSPIN_COMMUNICATION Communication; 00745 MIXER_STATUS Status; 00746 KSP_PIN Request; 00747 ULONG BytesReturned; 00748 GUID Guid; 00749 BOOLEAN BridgePin = FALSE; 00750 PKSPIN_PHYSICALCONNECTION Connection; 00751 00752 /* first dataflow type */ 00753 Status = MMixerGetPinDataFlowAndCommunication(MixerContext, hMixer, PinId, &DataFlow, &Communication); 00754 00755 if (Status != MM_STATUS_SUCCESS) 00756 { 00757 /* failed to get dataflow */ 00758 return Status; 00759 } 00760 00761 /* now get pin category guid */ 00762 Request.PinId = PinId; 00763 Request.Reserved = 0; 00764 Request.Property.Flags = KSPROPERTY_TYPE_GET; 00765 Request.Property.Set = KSPROPSETID_Pin; 00766 Request.Property.Id = KSPROPERTY_PIN_CATEGORY; 00767 00768 00769 /* get pin category */ 00770 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_PIN), &Guid, sizeof(GUID), &BytesReturned); 00771 if (Status != MM_STATUS_SUCCESS) 00772 { 00773 /* failed to get dataflow */ 00774 return Status; 00775 } 00776 00777 /* check if it has a physical connection */ 00778 Status = MMixerGetPhysicalConnection(MixerContext, hMixer, PinId, &Connection); 00779 if (Status == MM_STATUS_SUCCESS) 00780 { 00781 /* pin is a brige pin */ 00782 BridgePin = TRUE; 00783 00784 /* free physical connection */ 00785 MixerContext->Free(Connection); 00786 } 00787 00788 if (DataFlow == KSPIN_DATAFLOW_IN) 00789 { 00790 if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_MICROPHONE) || 00791 IsEqualGUIDAligned(&Guid, &KSNODETYPE_DESKTOP_MICROPHONE)) 00792 { 00793 /* type microphone */ 00794 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; 00795 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE; 00796 } 00797 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_LEGACY_AUDIO_CONNECTOR) || 00798 IsEqualGUIDAligned(&Guid, &KSCATEGORY_AUDIO) || 00799 IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPEAKER)) 00800 { 00801 /* type waveout */ 00802 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; 00803 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT; 00804 } 00805 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_CD_PLAYER)) 00806 { 00807 /* type cd player */ 00808 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; 00809 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; 00810 } 00811 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SYNTHESIZER)) 00812 { 00813 /* type synthesizer */ 00814 *TargetType = MIXERLINE_TARGETTYPE_MIDIOUT; 00815 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER; 00816 } 00817 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_LINE_CONNECTOR)) 00818 { 00819 /* type line */ 00820 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; 00821 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE; 00822 } 00823 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_TELEPHONE) || 00824 IsEqualGUIDAligned(&Guid, &KSNODETYPE_PHONE_LINE) || 00825 IsEqualGUIDAligned(&Guid, &KSNODETYPE_DOWN_LINE_PHONE)) 00826 { 00827 /* type telephone */ 00828 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; 00829 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE; 00830 } 00831 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_ANALOG_CONNECTOR)) 00832 { 00833 /* type analog */ 00834 if (BridgePin) 00835 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; 00836 else 00837 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; 00838 00839 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_ANALOG; 00840 } 00841 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPDIF_INTERFACE)) 00842 { 00843 /* type analog */ 00844 if (BridgePin) 00845 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; 00846 else 00847 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; 00848 00849 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL; 00850 } 00851 else 00852 { 00853 /* unknown type */ 00854 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; 00855 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED; 00856 DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin); 00857 } 00858 } 00859 else 00860 { 00861 if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPEAKER) || 00862 IsEqualGUIDAligned(&Guid, &KSNODETYPE_DESKTOP_SPEAKER) || 00863 IsEqualGUIDAligned(&Guid, &KSNODETYPE_ROOM_SPEAKER) || 00864 IsEqualGUIDAligned(&Guid, &KSNODETYPE_COMMUNICATION_SPEAKER)) 00865 { 00866 /* type waveout */ 00867 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; 00868 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; 00869 } 00870 else if (IsEqualGUIDAligned(&Guid, &KSCATEGORY_AUDIO) || 00871 IsEqualGUIDAligned(&Guid, &PINNAME_CAPTURE)) 00872 { 00873 /* type wavein */ 00874 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; 00875 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; 00876 } 00877 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_HEADPHONES) || 00878 IsEqualGUIDAligned(&Guid, &KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO)) 00879 { 00880 /* type head phones */ 00881 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; 00882 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES; 00883 } 00884 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_TELEPHONE) || 00885 IsEqualGUIDAligned(&Guid, &KSNODETYPE_PHONE_LINE) || 00886 IsEqualGUIDAligned(&Guid, &KSNODETYPE_DOWN_LINE_PHONE)) 00887 { 00888 /* type waveout */ 00889 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; 00890 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_TELEPHONE; 00891 } 00892 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_ANALOG_CONNECTOR)) 00893 { 00894 /* type analog */ 00895 if (BridgePin) 00896 { 00897 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; 00898 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; 00899 } 00900 else 00901 { 00902 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; 00903 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; 00904 } 00905 } 00906 else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPDIF_INTERFACE)) 00907 { 00908 /* type spdif */ 00909 if (BridgePin) 00910 { 00911 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; 00912 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; 00913 } 00914 else 00915 { 00916 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; 00917 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; 00918 } 00919 } 00920 else 00921 { 00922 /* unknown type */ 00923 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; 00924 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED; 00925 DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin); 00926 } 00927 } 00928 00929 /* done */ 00930 return MM_STATUS_SUCCESS; 00931 } 00932 00933 MIXER_STATUS 00934 MMixerBuildMixerSourceLine( 00935 IN PMIXER_CONTEXT MixerContext, 00936 IN OUT LPMIXER_INFO MixerInfo, 00937 IN HANDLE hMixer, 00938 IN PTOPOLOGY Topology, 00939 IN ULONG PinId, 00940 IN ULONG NodesCount, 00941 IN PULONG Nodes, 00942 IN ULONG DestinationLineID, 00943 OUT LPMIXERLINE_EXT * OutSrcLine) 00944 { 00945 LPMIXERLINE_EXT SrcLine, DstLine; 00946 LPWSTR PinName; 00947 MIXER_STATUS Status; 00948 ULONG ComponentType, TargetType; 00949 00950 /* get component and target type */ 00951 Status = MMixerGetComponentAndTargetType(MixerContext, MixerInfo, hMixer, PinId, &ComponentType, &TargetType); 00952 if (Status != MM_STATUS_SUCCESS) 00953 { 00954 /* failed to get component status */ 00955 TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; 00956 ComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED; 00957 } 00958 00959 /* construct source line */ 00960 SrcLine = (LPMIXERLINE_EXT)MixerContext->Alloc(sizeof(MIXERLINE_EXT)); 00961 00962 if (!SrcLine) 00963 { 00964 /* no memory */ 00965 return MM_STATUS_NO_MEMORY; 00966 } 00967 00968 /* get destination line */ 00969 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); 00970 ASSERT(DstLine); 00971 00972 /* initialize mixer src line */ 00973 SrcLine->PinId = PinId; 00974 00975 /* initialize mixer line */ 00976 SrcLine->Line.cbStruct = sizeof(MIXERLINEW); 00977 SrcLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations-1; 00978 SrcLine->Line.dwSource = DstLine->Line.cConnections; 00979 SrcLine->Line.dwLineID = (DstLine->Line.cConnections * SOURCE_LINE)+ (MixerInfo->MixCaps.cDestinations-1); 00980 SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE; 00981 SrcLine->Line.dwComponentType = ComponentType; 00982 SrcLine->Line.dwUser = 0; 00983 SrcLine->Line.cChannels = DstLine->Line.cChannels; 00984 SrcLine->Line.cConnections = 0; 00985 SrcLine->Line.Target.dwType = TargetType; 00986 SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID; 00987 SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid; 00988 SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid; 00989 SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; 00990 InitializeListHead(&SrcLine->ControlsList); 00991 00992 /* copy name */ 00993 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == L'\0'); 00994 wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname); 00995 00996 /* get pin name */ 00997 Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName); 00998 00999 if (Status == MM_STATUS_SUCCESS) 01000 { 01001 /* store pin name as line name */ 01002 MixerContext->Copy(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR)); 01003 SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; 01004 01005 MixerContext->Copy(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR)); 01006 SrcLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; 01007 01008 /* free pin name buffer */ 01009 MixerContext->Free(PinName); 01010 } 01011 01012 /* add the controls to mixer line */ 01013 Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, SrcLine, NodesCount, Nodes); 01014 if (Status != MM_STATUS_SUCCESS) 01015 { 01016 /* failed */ 01017 return Status; 01018 } 01019 01020 /* store result */ 01021 *OutSrcLine = SrcLine; 01022 01023 return MM_STATUS_SUCCESS; 01024 } 01025 01026 MIXER_STATUS 01027 MMixerAddMixerSourceLines( 01028 IN PMIXER_CONTEXT MixerContext, 01029 IN OUT LPMIXER_INFO MixerInfo, 01030 IN HANDLE hMixer, 01031 IN PTOPOLOGY Topology, 01032 IN ULONG DestinationLineID, 01033 IN ULONG LineTerminator) 01034 { 01035 PULONG AllNodes, AllPins, AllPinNodes; 01036 ULONG AllNodesCount, AllPinsCount, AllPinNodesCount; 01037 ULONG Index, SubIndex, PinId, CurNode, bConnected; 01038 MIXER_STATUS Status; 01039 LPMIXERLINE_EXT DstLine, SrcLine; 01040 01041 /* get destination line */ 01042 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); 01043 ASSERT(DstLine); 01044 01045 /* allocate an array to store all nodes which are upstream of the line terminator */ 01046 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllNodes); 01047 01048 /* check for success */ 01049 if (Status != MM_STATUS_SUCCESS) 01050 { 01051 /* out of memory */ 01052 return MM_STATUS_NO_MEMORY; 01053 } 01054 01055 /* allocate an array to store all nodes which are downstream of a particular pin */ 01056 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllPinNodes); 01057 01058 /* allocate an array to store all pins which are upstream of this pin */ 01059 Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &AllPins); 01060 01061 /* check for success */ 01062 if (Status != MM_STATUS_SUCCESS) 01063 { 01064 /* out of memory */ 01065 MixerContext->Free(AllNodes); 01066 return MM_STATUS_NO_MEMORY; 01067 } 01068 01069 /* get all nodes which indirectly / directly connect to this node */ 01070 AllNodesCount = 0; 01071 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllNodesCount, AllNodes); 01072 01073 /* get all pins which indirectly / directly connect to this node */ 01074 AllPinsCount = 0; 01075 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllPinsCount, AllPins); 01076 01077 DPRINT("LineTerminator %lu\n", LineTerminator); 01078 DPRINT("PinCount %lu\n", AllPinsCount); 01079 DPRINT("AllNodesCount %lu\n", AllNodesCount); 01080 01081 /* now construct the source lines which are attached to the destination line */ 01082 Index = AllPinsCount; 01083 01084 do 01085 { 01086 /* get current pin id */ 01087 PinId = AllPins[Index - 1]; 01088 01089 /* reset nodes count */ 01090 AllPinNodesCount = 0; 01091 01092 /* now scan all nodes and add them to AllPinNodes array when they are connected to this pin */ 01093 for(SubIndex = 0; SubIndex < AllNodesCount; SubIndex++) 01094 { 01095 /* get current node index */ 01096 CurNode = AllNodes[SubIndex]; 01097 01098 if (CurNode != MAXULONG && CurNode != LineTerminator) 01099 { 01100 /* check if that node is connected in some way to the current pin */ 01101 Status = MMixerIsNodeConnectedToPin(MixerContext, Topology, CurNode, PinId, TRUE, &bConnected); 01102 01103 if (Status != MM_STATUS_SUCCESS) 01104 break; 01105 01106 if (bConnected) 01107 { 01108 /* it is connected */ 01109 AllPinNodes[AllPinNodesCount] = CurNode; 01110 AllPinNodesCount++; 01111 01112 /* clear current index */ 01113 AllNodes[SubIndex] = MAXULONG; 01114 } 01115 } 01116 } 01117 01118 /* decrement pin index */ 01119 Index--; 01120 01121 if (AllPinNodesCount) 01122 { 01123 #ifdef MMIXER_DEBUG 01124 ULONG TempIndex; 01125 #endif 01126 /* now build the mixer source line */ 01127 Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, hMixer, Topology, PinId, AllPinNodesCount, AllPinNodes, DestinationLineID, &SrcLine); 01128 01129 if (Status == MM_STATUS_SUCCESS) 01130 { 01131 /* insert into line list */ 01132 InsertTailList(&MixerInfo->LineList, &SrcLine->Entry); 01133 01134 /* increment destination line count */ 01135 DstLine->Line.cConnections++; 01136 01137 /* mark pin as reserved */ 01138 MMixerSetTopologyPinReserved(Topology, PinId); 01139 01140 #ifdef MMIXER_DEBUG 01141 DPRINT1("Adding PinId %lu AllPinNodesCount %lu to DestinationLine %lu\n", PinId, AllPinNodesCount, DestinationLineID); 01142 for(TempIndex = 0; TempIndex < AllPinNodesCount; TempIndex++) 01143 DPRINT1("NodeIndex %lu\n", AllPinNodes[TempIndex]); 01144 #endif 01145 } 01146 } 01147 else 01148 { 01149 #ifdef MMIXER_DEBUG 01150 DPRINT1("Discarding DestinationLineID %lu PinId %lu NO NODES!\n", DestinationLineID, PinId); 01151 #endif 01152 } 01153 01154 }while(Index != 0); 01155 01156 return MM_STATUS_SUCCESS; 01157 } 01158 01159 01160 MIXER_STATUS 01161 MMixerAddMixerControlsToDestinationLine( 01162 IN PMIXER_CONTEXT MixerContext, 01163 IN OUT LPMIXER_INFO MixerInfo, 01164 IN HANDLE hMixer, 01165 IN PTOPOLOGY Topology, 01166 IN ULONG PinId, 01167 IN ULONG bInput, 01168 IN ULONG DestinationLineId, 01169 OUT PULONG OutLineTerminator) 01170 { 01171 PULONG Nodes; 01172 ULONG NodesCount, LineTerminator; 01173 MIXER_STATUS Status; 01174 LPMIXERLINE_EXT DstLine; 01175 01176 /* allocate nodes index array */ 01177 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &Nodes); 01178 01179 /* check for success */ 01180 if (Status != MM_STATUS_SUCCESS) 01181 { 01182 /* out of memory */ 01183 return Status; 01184 } 01185 01186 /* get all destination line controls */ 01187 Status = MMixerCountMixerControls(MixerContext, Topology, PinId, bInput, TRUE, &NodesCount, Nodes, &LineTerminator); 01188 01189 /* check for success */ 01190 if (Status != MM_STATUS_SUCCESS) 01191 { 01192 /* failed to count controls */ 01193 MixerContext->Free(Nodes); 01194 return Status; 01195 } 01196 01197 /* get destination mixer line */ 01198 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineId); 01199 01200 /* sanity check */ 01201 ASSERT(DstLine); 01202 01203 if (NodesCount > 0) 01204 { 01205 /* add all nodes as mixer controls to the destination line */ 01206 Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, DstLine, NodesCount, Nodes); 01207 if (Status != MM_STATUS_SUCCESS) 01208 { 01209 /* failed to add controls */ 01210 MixerContext->Free(Nodes); 01211 return Status; 01212 } 01213 } 01214 01215 /* store result */ 01216 *OutLineTerminator = LineTerminator; 01217 01218 /* return result */ 01219 return Status; 01220 } 01221 01222 VOID 01223 MMixerApplyOutputFilterHack( 01224 IN PMIXER_CONTEXT MixerContext, 01225 IN LPMIXER_DATA MixerData, 01226 IN HANDLE hMixer, 01227 IN OUT PULONG PinsCount, 01228 IN OUT PULONG Pins) 01229 { 01230 ULONG Count = 0, Index; 01231 MIXER_STATUS Status; 01232 PKSPIN_PHYSICALCONNECTION Connection; 01233 01234 for(Index = 0; Index < *PinsCount; Index++) 01235 { 01236 /* check if it has a physical connection */ 01237 Status = MMixerGetPhysicalConnection(MixerContext, hMixer, Pins[Index], &Connection); 01238 01239 if (Status == MM_STATUS_SUCCESS) 01240 { 01241 /* remove pin */ 01242 MixerContext->Copy(&Pins[Index], &Pins[Index + 1], (*PinsCount - (Index + 1)) * sizeof(ULONG)); 01243 01244 /* free physical connection */ 01245 MixerContext->Free(Connection); 01246 01247 /* decrement index */ 01248 Index--; 01249 01250 /* decrement pin count */ 01251 (*PinsCount)--; 01252 } 01253 else 01254 { 01255 /* simple pin */ 01256 Count++; 01257 } 01258 } 01259 01260 /* store result */ 01261 *PinsCount = Count; 01262 } 01263 01264 MIXER_STATUS 01265 MMixerHandlePhysicalConnection( 01266 IN PMIXER_CONTEXT MixerContext, 01267 IN PMIXER_LIST MixerList, 01268 IN LPMIXER_DATA MixerData, 01269 IN OUT LPMIXER_INFO MixerInfo, 01270 IN ULONG bInput, 01271 IN PKSPIN_PHYSICALCONNECTION OutConnection) 01272 { 01273 MIXER_STATUS Status; 01274 ULONG PinsCount, LineTerminator, DestinationLineID; 01275 PULONG Pins; 01276 PTOPOLOGY Topology; 01277 01278 /* first try to open the connected filter */ 01279 OutConnection->SymbolicLinkName[1] = L'\\'; 01280 MixerData = MMixerGetDataByDeviceName(MixerList, OutConnection->SymbolicLinkName); 01281 01282 /* check if the linked connection is found */ 01283 if (!MixerData) 01284 { 01285 /* filter references invalid physical connection */ 01286 return MM_STATUS_UNSUCCESSFUL; 01287 } 01288 01289 DPRINT("Name %S, Pin %lu bInput %lu\n", OutConnection->SymbolicLinkName, OutConnection->Pin, bInput); 01290 01291 /* sanity check */ 01292 ASSERT(MixerData->MixerInfo == NULL || MixerData->MixerInfo == MixerInfo); 01293 01294 /* associate with mixer */ 01295 MixerData->MixerInfo = MixerInfo; 01296 01297 if (MixerData->Topology == NULL) 01298 { 01299 /* construct new topology */ 01300 Status = MMixerBuildTopology(MixerContext, MixerData, &Topology); 01301 if (Status != MM_STATUS_SUCCESS) 01302 { 01303 /* failed to create topology */ 01304 return Status; 01305 } 01306 01307 /* store topology */ 01308 MixerData->Topology = Topology; 01309 } 01310 else 01311 { 01312 /* re-use existing topology */ 01313 Topology = MixerData->Topology; 01314 } 01315 01316 /* mark pin as consumed */ 01317 MMixerSetTopologyPinReserved(Topology, OutConnection->Pin); 01318 01319 if (!bInput) 01320 { 01321 /* allocate pin index array which will hold all referenced pins */ 01322 Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins); 01323 if (Status != MM_STATUS_SUCCESS) 01324 { 01325 /* failed to create topology */ 01326 return Status; 01327 } 01328 01329 /* the mixer is an output mixer 01330 * find end pin of the node path 01331 */ 01332 PinsCount = 0; 01333 Status = MMixerGetAllUpOrDownstreamPinsFromPinIndex(MixerContext, Topology, OutConnection->Pin, FALSE, &PinsCount, Pins); 01334 01335 /* check for success */ 01336 if (Status != MM_STATUS_SUCCESS) 01337 { 01338 /* failed to get end pin */ 01339 MixerContext->Free(Pins); 01340 //MMixerFreeTopology(Topology); 01341 01342 /* return error code */ 01343 return Status; 01344 } 01345 /* HACK: 01346 * some topologies do not have strict boundaries 01347 * WorkArround: remove all pin ids which have a physical connection 01348 * because bridge pins may belong to different render paths 01349 */ 01350 MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins); 01351 01352 /* sanity checks */ 01353 ASSERT(PinsCount != 0); 01354 ASSERT(PinsCount == 1); 01355 01356 /* create destination line */ 01357 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput); 01358 01359 /* calculate destination line id */ 01360 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1); 01361 01362 if (Status != MM_STATUS_SUCCESS) 01363 { 01364 /* failed to build destination line */ 01365 MixerContext->Free(Pins); 01366 01367 /* return error code */ 01368 return Status; 01369 } 01370 01371 /* add mixer controls to destination line */ 01372 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator); 01373 01374 if (Status == MM_STATUS_SUCCESS) 01375 { 01376 /* now add the rest of the source lines */ 01377 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator); 01378 } 01379 01380 /* mark pin as consumed */ 01381 MMixerSetTopologyPinReserved(Topology, Pins[0]); 01382 01383 /* free topology pin array */ 01384 MixerContext->Free(Pins); 01385 } 01386 else 01387 { 01388 /* calculate destination line id */ 01389 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1); 01390 01391 /* add mixer controls */ 01392 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, OutConnection->Pin, bInput, DestinationLineID, &LineTerminator); 01393 01394 if (Status == MM_STATUS_SUCCESS) 01395 { 01396 /* now add the rest of the source lines */ 01397 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator); 01398 } 01399 } 01400 01401 return Status; 01402 } 01403 01404 MIXER_STATUS 01405 MMixerInitializeFilter( 01406 IN PMIXER_CONTEXT MixerContext, 01407 IN PMIXER_LIST MixerList, 01408 IN LPMIXER_DATA MixerData, 01409 IN LPMIXER_INFO MixerInfo, 01410 IN PTOPOLOGY Topology, 01411 IN ULONG NodeIndex, 01412 IN ULONG bInputMixer, 01413 IN OUT LPMIXER_INFO * OutMixerInfo) 01414 { 01415 ULONG Index; 01416 MIXER_STATUS Status; 01417 PKSPIN_PHYSICALCONNECTION OutConnection; 01418 ULONG * Pins; 01419 ULONG PinsFound; 01420 ULONG NewMixerInfo = FALSE; 01421 01422 if (MixerInfo == NULL) 01423 { 01424 /* allocate a mixer info struct */ 01425 MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO)); 01426 if (!MixerInfo) 01427 { 01428 /* no memory */ 01429 return MM_STATUS_NO_MEMORY; 01430 } 01431 01432 /* new mixer info */ 01433 NewMixerInfo = TRUE; 01434 01435 /* intialize mixer caps */ 01436 MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */ 01437 MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */ 01438 MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */ 01439 MixerInfo->MixCaps.fdwSupport = 0; 01440 MixerInfo->MixCaps.cDestinations = 0; 01441 01442 /* get mixer name */ 01443 MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey); 01444 01445 /* initialize line list */ 01446 InitializeListHead(&MixerInfo->LineList); 01447 InitializeListHead(&MixerInfo->EventList); 01448 01449 /* associate with mixer data */ 01450 MixerData->MixerInfo = MixerInfo; 01451 } 01452 01453 /* store mixer info */ 01454 *OutMixerInfo = MixerInfo; 01455 01456 /* now allocate an array which will receive the indices of the pin 01457 * which has a ADC / DAC nodetype in its path 01458 */ 01459 Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins); 01460 ASSERT(Status == MM_STATUS_SUCCESS); 01461 01462 PinsFound = 0; 01463 01464 /* now get all sink / source pins, which are attached to the ADC / DAC node 01465 * For sink pins (wave out) search up stream 01466 * For source pins (wave in) search down stream 01467 * The search direction is always the opposite of the current mixer type 01468 */ 01469 PinsFound = 0; 01470 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins); 01471 01472 /* if there is no pin found, we have a broken topology */ 01473 ASSERT(PinsFound != 0); 01474 01475 /* now create a wave info struct */ 01476 Status = MMixerInitializeWaveInfo(MixerContext, MixerList, MixerData, MixerInfo->MixCaps.szPname, bInputMixer, PinsFound, Pins); 01477 if (Status != MM_STATUS_SUCCESS) 01478 { 01479 /* failed to create wave info struct */ 01480 MixerContext->Free(MixerInfo); 01481 MixerContext->Free(Pins); 01482 return Status; 01483 } 01484 01485 /* mark all found pins as reserved */ 01486 for(Index = 0; Index < PinsFound; Index++) 01487 { 01488 MMixerSetTopologyPinReserved(Topology, Pins[Index]); 01489 } 01490 01491 if (bInputMixer) 01492 { 01493 /* pre create the mixer destination line for input mixers */ 01494 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInputMixer); 01495 01496 if (Status != MM_STATUS_SUCCESS) 01497 { 01498 /* failed to create mixer destination line */ 01499 return Status; 01500 } 01501 } 01502 01503 01504 /* now get the bridge pin which is at the end of node path 01505 * For sink pins (wave out) search down stream 01506 * For source pins (wave in) search up stream 01507 */ 01508 MixerContext->Free(Pins); 01509 Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins); 01510 ASSERT(Status == MM_STATUS_SUCCESS); 01511 01512 PinsFound = 0; 01513 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, bInputMixer, &PinsFound, Pins); 01514 01515 /* if there is no pin found, we have a broken topology */ 01516 ASSERT(PinsFound != 0); 01517 01518 /* there should be exactly one bridge pin */ 01519 ASSERT(PinsFound == 1); 01520 01521 DPRINT("BridgePin %lu bInputMixer %lu\n", Pins[0], bInputMixer); 01522 01523 /* does the pin have a physical connection */ 01524 Status = MMixerGetPhysicalConnection(MixerContext, MixerData->hDevice, Pins[0], &OutConnection); 01525 01526 if (Status == MM_STATUS_SUCCESS) 01527 { 01528 /* mark pin as reserved */ 01529 MMixerSetTopologyPinReserved(Topology, Pins[0]); 01530 01531 /* topology on the topoloy filter */ 01532 Status = MMixerHandlePhysicalConnection(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, OutConnection); 01533 01534 /* free physical connection data */ 01535 MixerContext->Free(OutConnection); 01536 } 01537 else 01538 { 01539 /* FIXME 01540 * handle drivers which expose their topology on the same filter 01541 */ 01542 ASSERT(0); 01543 } 01544 01545 /* free pins */ 01546 MixerContext->Free(Pins); 01547 01548 if (NewMixerInfo) 01549 { 01550 /* insert mixer */ 01551 InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry); 01552 /* increment mixer count */ 01553 MixerList->MixerListCount++; 01554 } 01555 01556 /* done */ 01557 return Status; 01558 } 01559 01560 VOID 01561 MMixerHandleAlternativeMixers( 01562 IN PMIXER_CONTEXT MixerContext, 01563 IN PMIXER_LIST MixerList, 01564 IN LPMIXER_DATA MixerData, 01565 IN PTOPOLOGY Topology) 01566 { 01567 ULONG Index, PinCount, Reserved; 01568 MIXER_STATUS Status; 01569 ULONG DestinationLineID, LineTerminator; 01570 LPMIXERLINE_EXT DstLine; 01571 01572 DPRINT("DeviceName %S\n", MixerData->DeviceName); 01573 01574 /* get topology pin count */ 01575 MMixerGetTopologyPinCount(Topology, &PinCount); 01576 01577 for(Index = 0; Index < PinCount; Index++) 01578 { 01579 MMixerIsTopologyPinReserved(Topology, Index, &Reserved); 01580 01581 /* check if it has already been reserved */ 01582 if (Reserved == TRUE) 01583 { 01584 /* pin has already been reserved */ 01585 continue; 01586 } 01587 01588 DPRINT("MixerName %S Available PinID %lu\n", MixerData->DeviceName, Index); 01589 01590 /* sanity check */ 01591 //ASSERT(MixerData->MixerInfo); 01592 01593 if (!MixerData->MixerInfo) 01594 { 01595 DPRINT1("Expected mixer info\n"); 01596 continue; 01597 } 01598 01599 /* build the destination line */ 01600 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, Index, TRUE); 01601 if (Status != MM_STATUS_SUCCESS) 01602 { 01603 /* failed to build destination line */ 01604 continue; 01605 } 01606 01607 /* calculate destination line id */ 01608 DestinationLineID = (DESTINATION_LINE + MixerData->MixerInfo->MixCaps.cDestinations-1); 01609 01610 /* add mixer controls to destination line */ 01611 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, Index, TRUE, DestinationLineID, &LineTerminator); 01612 if (Status == MM_STATUS_SUCCESS) 01613 { 01614 /* now add the rest of the source lines */ 01615 Status = MMixerAddMixerSourceLines(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, DestinationLineID, LineTerminator); 01616 } 01617 01618 /* mark pin as consumed */ 01619 MMixerSetTopologyPinReserved(Topology, Index); 01620 01621 /* now grab destination line */ 01622 DstLine = MMixerGetSourceMixerLineByLineId(MixerData->MixerInfo, DestinationLineID); 01623 01624 /* set type and target as undefined */ 01625 DstLine->Line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED; 01626 DstLine->Line.Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED; 01627 DstLine->Line.Target.vDriverVersion = 0; 01628 DstLine->Line.Target.wMid = 0; 01629 DstLine->Line.Target.wPid = 0; 01630 } 01631 } 01632 01633 MIXER_STATUS 01634 MMixerSetupFilter( 01635 IN PMIXER_CONTEXT MixerContext, 01636 IN PMIXER_LIST MixerList, 01637 IN LPMIXER_DATA MixerData, 01638 IN PULONG DeviceCount) 01639 { 01640 MIXER_STATUS Status; 01641 PTOPOLOGY Topology; 01642 ULONG NodeIndex; 01643 LPMIXER_INFO MixerInfo = NULL; 01644 01645 /* check if topology has already been built */ 01646 if (MixerData->Topology == NULL) 01647 { 01648 /* build topology */ 01649 Status = MMixerBuildTopology(MixerContext, MixerData, &Topology); 01650 01651 if (Status != MM_STATUS_SUCCESS) 01652 { 01653 /* failed to build topology */ 01654 return Status; 01655 } 01656 01657 /* store topology */ 01658 MixerData->Topology = Topology; 01659 } 01660 else 01661 { 01662 /* re-use topology */ 01663 Topology = MixerData->Topology; 01664 } 01665 01666 /* check if the filter has an wave out node */ 01667 NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_DAC); 01668 if (NodeIndex != MAXULONG) 01669 { 01670 /* it has */ 01671 Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NULL, Topology, NodeIndex, FALSE, &MixerInfo); 01672 01673 /* check for success */ 01674 if (Status == MM_STATUS_SUCCESS) 01675 { 01676 /* increment mixer count */ 01677 (*DeviceCount)++; 01678 } 01679 else 01680 { 01681 /* reset mixer info in case of error */ 01682 MixerInfo = NULL; 01683 } 01684 } 01685 01686 /* check if the filter has an wave in node */ 01687 NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_ADC); 01688 if (NodeIndex != MAXULONG) 01689 { 01690 /* it has */ 01691 Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, MixerInfo, Topology, NodeIndex, TRUE, &MixerInfo); 01692 01693 /* check for success */ 01694 if (Status == MM_STATUS_SUCCESS) 01695 { 01696 /* increment mixer count */ 01697 (*DeviceCount)++; 01698 } 01699 01700 } 01701 01702 /* TODO: apply hacks for Wave source line */ 01703 01704 /* activate midi devices */ 01705 //MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology); 01706 01707 /* done */ 01708 return Status; 01709 } 01710 01711 01712 MIXER_STATUS 01713 MMixerAddEvent( 01714 IN PMIXER_CONTEXT MixerContext, 01715 IN OUT LPMIXER_INFO MixerInfo, 01716 IN PVOID MixerEventContext, 01717 IN PMIXER_EVENT MixerEventRoutine) 01718 { 01719 //KSE_NODE Property; 01720 PEVENT_NOTIFICATION_ENTRY EventData; 01721 //ULONG BytesReturned; 01722 //MIXER_STATUS Status; 01723 01724 EventData = (PEVENT_NOTIFICATION_ENTRY)MixerContext->AllocEventData(sizeof(EVENT_NOTIFICATION_ENTRY)); 01725 if (!EventData) 01726 { 01727 /* not enough memory */ 01728 return MM_STATUS_NO_MEMORY; 01729 } 01730 01731 #if 0 01732 /* setup request */ 01733 Property.Event.Set = KSEVENTSETID_AudioControlChange; 01734 Property.Event.Flags = KSEVENT_TYPE_TOPOLOGY|KSEVENT_TYPE_ENABLE; 01735 Property.Event.Id = KSEVENT_CONTROL_CHANGE; 01736 01737 Property.NodeId = NodeId; 01738 Property.Reserved = 0; 01739 01740 Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSP_NODE), (PVOID)EventData, sizeof(KSEVENTDATA), &BytesReturned); 01741 if (Status != MM_STATUS_SUCCESS) 01742 { 01743 /* failed to add event */ 01744 MixerContext->FreeEventData(EventData); 01745 return Status; 01746 } 01747 #endif 01748 01749 /* initialize notification entry */ 01750 EventData->MixerEventContext = MixerEventContext; 01751 EventData->MixerEventRoutine = MixerEventRoutine; 01752 01753 /* store event */ 01754 InsertTailList(&MixerInfo->EventList, &EventData->Entry); 01755 return MM_STATUS_SUCCESS; 01756 } 01757 Generated on Fri May 25 2012 04:34:39 for ReactOS by
1.7.6.1
|