Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensup.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/sup.c 00005 * PURPOSE: Mixer Support Functions 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 00010 00011 #include "priv.h" 00012 00013 const GUID KSNODETYPE_SUM = {0xDA441A60L, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00014 const GUID KSNODETYPE_DAC = {0x507AE360L, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00015 const GUID KSNODETYPE_ADC = {0x4D837FE0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00016 const GUID KSNODETYPE_AGC = {0xE88C9BA0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00017 const GUID KSNODETYPE_LOUDNESS = {0x41887440L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00018 const GUID KSNODETYPE_MUTE = {0x02B223C0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00019 const GUID KSNODETYPE_TONE = {0x7607E580L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00020 const GUID KSNODETYPE_VOLUME = {0x3A5ACC00L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00021 const GUID KSNODETYPE_PEAKMETER = {0xa085651e, 0x5f0d, 0x4b36, {0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e}}; 00022 const GUID KSNODETYPE_MUX = {0x2CEAF780, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00023 const GUID KSNODETYPE_STEREO_WIDE = {0xA9E69800L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00024 const GUID KSNODETYPE_CHORUS = {0x20173F20L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00025 const GUID KSNODETYPE_REVERB = {0xEF0328E0L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00026 const GUID KSNODETYPE_SUPERMIX = {0xE573ADC0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; 00027 00028 const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; 00029 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}}; 00030 const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00031 const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00032 const GUID KSEVENTSETID_AudioControlChange = {0xE85E9698L, 0xFA2F, 0x11D1, {0x95, 0xBD, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; 00033 00034 const GUID KSDATAFORMAT_TYPE_MUSIC = {0xE725D360L, 0x62CC, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00035 const GUID KSDATAFORMAT_SUBTYPE_MIDI = {0x1D262760L, 0xE957, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00036 const GUID KSDATAFORMAT_SPECIFIER_NONE = {0x0F6417D6L, 0xC318, 0x11D0, {0xA4, 0x3F, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00037 00038 00039 MIXER_STATUS 00040 MMixerVerifyContext( 00041 IN PMIXER_CONTEXT MixerContext) 00042 { 00043 if (MixerContext->SizeOfStruct != sizeof(MIXER_CONTEXT)) 00044 return MM_STATUS_INVALID_PARAMETER; 00045 00046 if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open || 00047 !MixerContext->AllocEventData || !MixerContext->FreeEventData || 00048 !MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey) 00049 return MM_STATUS_INVALID_PARAMETER; 00050 00051 if (!MixerContext->MixerContext) 00052 return MM_STATUS_INVALID_PARAMETER; 00053 00054 return MM_STATUS_SUCCESS; 00055 } 00056 00057 LPMIXERLINE_EXT 00058 MMixerGetMixerLineContainingNodeId( 00059 IN LPMIXER_INFO MixerInfo, 00060 IN ULONG NodeID) 00061 { 00062 PLIST_ENTRY Entry, ControlEntry; 00063 LPMIXERLINE_EXT MixerLineSrc; 00064 LPMIXERCONTROL_EXT MixerControl; 00065 00066 /* get first entry */ 00067 Entry = MixerInfo->LineList.Flink; 00068 00069 while(Entry != &MixerInfo->LineList) 00070 { 00071 MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry); 00072 00073 ControlEntry = MixerLineSrc->ControlsList.Flink; 00074 while(ControlEntry != &MixerLineSrc->ControlsList) 00075 { 00076 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(ControlEntry, MIXERCONTROL_EXT, Entry); 00077 if (MixerControl->NodeID == NodeID) 00078 { 00079 return MixerLineSrc; 00080 } 00081 ControlEntry = ControlEntry->Flink; 00082 } 00083 Entry = Entry->Flink; 00084 } 00085 00086 return NULL; 00087 } 00088 00089 VOID 00090 MMixerGetLowestLogicalTopologyPinOffsetFromArray( 00091 IN ULONG LogicalPinArrayCount, 00092 IN PULONG LogicalPinArray, 00093 OUT PULONG PinOffset) 00094 { 00095 ULONG Index; 00096 ULONG LowestId = 0; 00097 00098 for(Index = 1; Index < LogicalPinArrayCount; Index++) 00099 { 00100 if (LogicalPinArray[Index] != MAXULONG) 00101 { 00102 /* sanity check: logical pin id must be unique */ 00103 ASSERT(LogicalPinArray[Index] != LogicalPinArray[LowestId]); 00104 } 00105 00106 if (LogicalPinArray[Index] < LogicalPinArray[LowestId]) 00107 LowestId = Index; 00108 } 00109 00110 /* store result */ 00111 *PinOffset = LowestId; 00112 } 00113 00114 VOID 00115 MMixerFreeMixerInfo( 00116 IN PMIXER_CONTEXT MixerContext, 00117 IN LPMIXER_INFO MixerInfo) 00118 { 00119 /* UNIMPLEMENTED 00120 * FIXME 00121 * free all lines 00122 */ 00123 00124 MixerContext->Free((PVOID)MixerInfo); 00125 } 00126 00127 00128 LPMIXER_DATA 00129 MMixerGetMixerDataByDeviceHandle( 00130 IN PMIXER_CONTEXT MixerContext, 00131 IN HANDLE hDevice) 00132 { 00133 LPMIXER_DATA MixerData; 00134 PLIST_ENTRY Entry; 00135 PMIXER_LIST MixerList; 00136 00137 /* get mixer list */ 00138 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 00139 00140 if (!MixerList->MixerDataCount) 00141 return NULL; 00142 00143 Entry = MixerList->MixerData.Flink; 00144 00145 while(Entry != &MixerList->MixerData) 00146 { 00147 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry); 00148 00149 if (MixerData->hDevice == hDevice) 00150 return MixerData; 00151 00152 /* move to next mixer entry */ 00153 Entry = Entry->Flink; 00154 } 00155 return NULL; 00156 } 00157 00158 00159 LPMIXER_INFO 00160 MMixerGetMixerInfoByIndex( 00161 IN PMIXER_CONTEXT MixerContext, 00162 IN ULONG MixerIndex) 00163 { 00164 LPMIXER_INFO MixerInfo; 00165 PLIST_ENTRY Entry; 00166 PMIXER_LIST MixerList; 00167 ULONG Index = 0; 00168 00169 /* get mixer list */ 00170 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 00171 00172 if (!MixerList->MixerListCount) 00173 return NULL; 00174 00175 Entry = MixerList->MixerList.Flink; 00176 00177 while(Entry != &MixerList->MixerList) 00178 { 00179 MixerInfo = (LPMIXER_INFO)CONTAINING_RECORD(Entry, MIXER_INFO, Entry); 00180 00181 if (Index == MixerIndex) 00182 return MixerInfo; 00183 00184 /* move to next mixer entry */ 00185 Index++; 00186 Entry = Entry->Flink; 00187 } 00188 00189 return NULL; 00190 } 00191 00192 MIXER_STATUS 00193 MMixerGetMixerByName( 00194 IN PMIXER_LIST MixerList, 00195 IN LPWSTR MixerName, 00196 OUT LPMIXER_INFO *OutMixerInfo) 00197 { 00198 LPMIXER_INFO MixerInfo; 00199 PLIST_ENTRY Entry; 00200 00201 Entry = MixerList->MixerList.Flink; 00202 while(Entry != &MixerList->MixerList) 00203 { 00204 MixerInfo = (LPMIXER_INFO)CONTAINING_RECORD(Entry, MIXER_INFO, Entry); 00205 00206 DPRINT1("MixerName %S MixerName %S\n", MixerInfo->MixCaps.szPname, MixerName); 00207 if (wcsicmp(MixerInfo->MixCaps.szPname, MixerName) == 0) 00208 { 00209 *OutMixerInfo = MixerInfo; 00210 return MM_STATUS_SUCCESS; 00211 } 00212 /* move to next mixer entry */ 00213 Entry = Entry->Flink; 00214 } 00215 00216 return MM_STATUS_UNSUCCESSFUL; 00217 } 00218 00219 LPMIXERLINE_EXT 00220 MMixerGetSourceMixerLineByLineId( 00221 LPMIXER_INFO MixerInfo, 00222 DWORD dwLineID) 00223 { 00224 PLIST_ENTRY Entry; 00225 LPMIXERLINE_EXT MixerLineSrc; 00226 00227 /* get first entry */ 00228 Entry = MixerInfo->LineList.Flink; 00229 00230 while(Entry != &MixerInfo->LineList) 00231 { 00232 MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry); 00233 DPRINT("dwLineID %x dwLineID %x MixerLineSrc %p\n", MixerLineSrc->Line.dwLineID, dwLineID, MixerLineSrc); 00234 if (MixerLineSrc->Line.dwLineID == dwLineID) 00235 return MixerLineSrc; 00236 00237 Entry = Entry->Flink; 00238 } 00239 00240 return NULL; 00241 } 00242 00243 LPGUID 00244 MMixerGetNodeType( 00245 IN PKSMULTIPLE_ITEM MultipleItem, 00246 IN ULONG Index) 00247 { 00248 LPGUID NodeType; 00249 00250 ASSERT(Index < MultipleItem->Count); 00251 00252 NodeType = (LPGUID)(MultipleItem + 1); 00253 return &NodeType[Index]; 00254 } 00255 00256 LPMIXERLINE_EXT 00257 MMixerGetSourceMixerLineByComponentType( 00258 LPMIXER_INFO MixerInfo, 00259 DWORD dwComponentType) 00260 { 00261 PLIST_ENTRY Entry; 00262 LPMIXERLINE_EXT MixerLineSrc; 00263 00264 /* get first entry */ 00265 Entry = MixerInfo->LineList.Flink; 00266 00267 while(Entry != &MixerInfo->LineList) 00268 { 00269 MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry); 00270 if (MixerLineSrc->Line.dwComponentType == dwComponentType) 00271 return MixerLineSrc; 00272 00273 Entry = Entry->Flink; 00274 } 00275 00276 return NULL; 00277 } 00278 00279 MIXER_STATUS 00280 MMixerGetMixerControlById( 00281 LPMIXER_INFO MixerInfo, 00282 DWORD dwControlID, 00283 LPMIXERLINE_EXT *OutMixerLine, 00284 LPMIXERCONTROL_EXT *OutMixerControl, 00285 PULONG NodeId) 00286 { 00287 PLIST_ENTRY Entry, ControlEntry; 00288 LPMIXERLINE_EXT MixerLineSrc; 00289 LPMIXERCONTROL_EXT MixerControl; 00290 00291 /* get first entry */ 00292 Entry = MixerInfo->LineList.Flink; 00293 00294 while(Entry != &MixerInfo->LineList) 00295 { 00296 MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry); 00297 00298 ControlEntry = MixerLineSrc->ControlsList.Flink; 00299 while(ControlEntry != &MixerLineSrc->ControlsList) 00300 { 00301 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(ControlEntry, MIXERCONTROL_EXT, Entry); 00302 if (MixerControl->Control.dwControlID == dwControlID) 00303 { 00304 if (OutMixerLine) 00305 *OutMixerLine = MixerLineSrc; 00306 if (OutMixerControl) 00307 *OutMixerControl = MixerControl; 00308 if (NodeId) 00309 *NodeId = MixerControl->NodeID; 00310 return MM_STATUS_SUCCESS; 00311 } 00312 ControlEntry = ControlEntry->Flink; 00313 } 00314 Entry = Entry->Flink; 00315 } 00316 00317 return MM_STATUS_UNSUCCESSFUL; 00318 } 00319 00320 ULONG 00321 MMixerGetVolumeControlIndex( 00322 LPMIXERVOLUME_DATA VolumeData, 00323 LONG Value) 00324 { 00325 ULONG Index; 00326 00327 for(Index = 0; Index < VolumeData->ValuesCount; Index++) 00328 { 00329 if (VolumeData->Values[Index] > Value) 00330 { 00331 return VolumeData->InputSteppingDelta * Index; 00332 } 00333 } 00334 return VolumeData->InputSteppingDelta * (VolumeData->ValuesCount-1); 00335 } 00336 00337 VOID 00338 MMixerNotifyControlChange( 00339 IN PMIXER_CONTEXT MixerContext, 00340 IN LPMIXER_INFO MixerInfo, 00341 IN ULONG NotificationType, 00342 IN ULONG Value) 00343 { 00344 PLIST_ENTRY Entry; 00345 PEVENT_NOTIFICATION_ENTRY NotificationEntry; 00346 00347 /* enumerate list and perform notification */ 00348 Entry = MixerInfo->EventList.Flink; 00349 while(Entry != &MixerInfo->EventList) 00350 { 00351 /* get notification entry offset */ 00352 NotificationEntry = (PEVENT_NOTIFICATION_ENTRY)CONTAINING_RECORD(Entry, EVENT_NOTIFICATION_ENTRY, Entry); 00353 00354 if (NotificationEntry->MixerEventRoutine) 00355 { 00356 /* now perform the callback */ 00357 NotificationEntry->MixerEventRoutine(NotificationEntry->MixerEventContext, (HANDLE)MixerInfo, NotificationType, Value); 00358 } 00359 00360 /* move to next notification entry */ 00361 Entry = Entry->Flink; 00362 } 00363 } 00364 00365 MIXER_STATUS 00366 MMixerSetGetMuteControlDetails( 00367 IN PMIXER_CONTEXT MixerContext, 00368 IN LPMIXER_INFO MixerInfo, 00369 IN LPMIXERCONTROL_EXT MixerControl, 00370 IN ULONG dwLineID, 00371 IN LPMIXERCONTROLDETAILS MixerControlDetails, 00372 IN ULONG bSet) 00373 { 00374 LPMIXERCONTROLDETAILS_BOOLEAN Input; 00375 LONG Value; 00376 MIXER_STATUS Status; 00377 00378 if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_BOOLEAN)) 00379 return MM_STATUS_INVALID_PARAMETER; 00380 00381 /* get input */ 00382 Input = (LPMIXERCONTROLDETAILS_BOOLEAN)MixerControlDetails->paDetails; 00383 00384 /* FIXME SEH */ 00385 if (bSet) 00386 Value = Input->fValue; 00387 00388 /* set control details */ 00389 Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, MixerControl->NodeID, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value); 00390 00391 if (Status != MM_STATUS_SUCCESS) 00392 return Status; 00393 00394 /* FIXME SEH */ 00395 if (!bSet) 00396 { 00397 Input->fValue = Value; 00398 return Status; 00399 } 00400 else 00401 { 00402 /* notify wdmaud clients MM_MIXM_LINE_CHANGE dwLineID */ 00403 MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_LINE_CHANGE, dwLineID); 00404 } 00405 00406 return Status; 00407 } 00408 00409 MIXER_STATUS 00410 MMixerSetGetMuxControlDetails( 00411 IN PMIXER_CONTEXT MixerContext, 00412 IN LPMIXER_INFO MixerInfo, 00413 IN ULONG NodeId, 00414 IN ULONG bSet, 00415 IN ULONG Flags, 00416 IN LPMIXERCONTROL_EXT MixerControl, 00417 IN LPMIXERCONTROLDETAILS MixerControlDetails, 00418 IN LPMIXERLINE_EXT MixerLine) 00419 { 00420 MIXER_STATUS Status; 00421 PULONG LogicalNodes, ConnectedNodes; 00422 ULONG LogicalNodesCount, ConnectedNodesCount, Index, CurLogicalPinOffset, BytesReturned, OldLogicalPinOffset; 00423 LPMIXER_DATA MixerData; 00424 LPMIXERCONTROLDETAILS_LISTTEXTW ListText; 00425 LPMIXERCONTROLDETAILS_BOOLEAN Values; 00426 LPMIXERLINE_EXT SourceLine; 00427 KSNODEPROPERTY Request; 00428 00429 DPRINT("MixerControlDetails %p\n", MixerControlDetails); 00430 DPRINT("bSet %lx\n", bSet); 00431 DPRINT("Flags %lx\n", Flags); 00432 DPRINT("NodeId %lu\n", MixerControl->NodeID); 00433 DPRINT("MixerControlDetails dwControlID %lu\n", MixerControlDetails->dwControlID); 00434 DPRINT("MixerControlDetails cChannels %lu\n", MixerControlDetails->cChannels); 00435 DPRINT("MixerControlDetails cMultipleItems %lu\n", MixerControlDetails->cMultipleItems); 00436 DPRINT("MixerControlDetails cbDetails %lu\n", MixerControlDetails->cbDetails); 00437 DPRINT("MixerControlDetails paDetails %p\n", MixerControlDetails->paDetails); 00438 00439 if (MixerControl->Control.fdwControl & MIXERCONTROL_CONTROLF_UNIFORM) 00440 { 00441 /* control acts uniform */ 00442 if (MixerControlDetails->cChannels != 1) 00443 { 00444 /* expected 1 channel */ 00445 DPRINT1("Expected 1 channel but got %lu\n", MixerControlDetails->cChannels); 00446 return MM_STATUS_UNSUCCESSFUL; 00447 } 00448 } 00449 00450 /* check if multiple items match */ 00451 if (MixerControlDetails->cMultipleItems != MixerControl->Control.cMultipleItems) 00452 { 00453 DPRINT1("MultipleItems mismatch %lu expected %lu\n", MixerControlDetails->cMultipleItems, MixerControl->Control.cMultipleItems); 00454 return MM_STATUS_UNSUCCESSFUL; 00455 } 00456 00457 if (bSet) 00458 { 00459 if ((Flags & MIXER_SETCONTROLDETAILSF_QUERYMASK) == MIXER_SETCONTROLDETAILSF_CUSTOM) 00460 { 00461 /* tell me when this is hit */ 00462 ASSERT(FALSE); 00463 } 00464 else if ((Flags & (MIXER_SETCONTROLDETAILSF_VALUE | MIXER_SETCONTROLDETAILSF_CUSTOM)) == MIXER_SETCONTROLDETAILSF_VALUE) 00465 { 00466 /* sanity check */ 00467 ASSERT(bSet == TRUE); 00468 ASSERT(MixerControlDetails->cbDetails == sizeof(MIXERCONTROLDETAILS_BOOLEAN)); 00469 00470 Values = (LPMIXERCONTROLDETAILS_BOOLEAN)MixerControlDetails->paDetails; 00471 CurLogicalPinOffset = MAXULONG; 00472 for(Index = 0; Index < MixerControlDetails->cMultipleItems; Index++) 00473 { 00474 if (Values[Index].fValue) 00475 { 00476 /* mux can only activate one line at a time */ 00477 ASSERT(CurLogicalPinOffset == MAXULONG); 00478 CurLogicalPinOffset = Index; 00479 } 00480 } 00481 00482 /* setup request */ 00483 Request.NodeId = NodeId; 00484 Request.Reserved = 0; 00485 Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_GET; 00486 Request.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE; 00487 Request.Property.Set = KSPROPSETID_Audio; 00488 00489 /* perform getting source */ 00490 Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &OldLogicalPinOffset, sizeof(ULONG), &BytesReturned); 00491 if (Status != MM_STATUS_SUCCESS) 00492 { 00493 /* failed to get source */ 00494 return Status; 00495 } 00496 00497 DPRINT("OldLogicalPinOffset %lu CurLogicalPinOffset %lu\n", OldLogicalPinOffset, CurLogicalPinOffset); 00498 00499 if (OldLogicalPinOffset == CurLogicalPinOffset) 00500 { 00501 /* cannot be unselected */ 00502 return MM_STATUS_UNSUCCESSFUL; 00503 } 00504 00505 /* perform setting source */ 00506 Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_SET; 00507 Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &CurLogicalPinOffset, sizeof(ULONG), &BytesReturned); 00508 if (Status != MM_STATUS_SUCCESS) 00509 { 00510 /* failed to set source */ 00511 return Status; 00512 } 00513 00514 /* notify control change */ 00515 MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->Control.dwControlID ); 00516 00517 return Status; 00518 } 00519 } 00520 else 00521 { 00522 if ((Flags & MIXER_GETCONTROLDETAILSF_QUERYMASK) == MIXER_GETCONTROLDETAILSF_VALUE) 00523 { 00524 /* setup request */ 00525 Request.NodeId = NodeId; 00526 Request.Reserved = 0; 00527 Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_GET; 00528 Request.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE; 00529 Request.Property.Set = KSPROPSETID_Audio; 00530 00531 /* perform getting source */ 00532 Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &OldLogicalPinOffset, sizeof(ULONG), &BytesReturned); 00533 if (Status != MM_STATUS_SUCCESS) 00534 { 00535 /* failed to get source */ 00536 return Status; 00537 } 00538 00539 /* gets the corresponding mixer data */ 00540 MixerData = MMixerGetMixerDataByDeviceHandle(MixerContext, MixerControl->hDevice); 00541 00542 /* sanity check */ 00543 ASSERT(MixerData); 00544 ASSERT(MixerData->Topology); 00545 ASSERT(MixerData->MixerInfo == MixerInfo); 00546 00547 /* now allocate logical pin array */ 00548 Status = MMixerAllocateTopologyNodeArray(MixerContext, MixerData->Topology, &LogicalNodes); 00549 if (Status != MM_STATUS_SUCCESS) 00550 { 00551 /* no memory */ 00552 return MM_STATUS_NO_MEMORY; 00553 } 00554 00555 /* get logical pin nodes */ 00556 MMixerGetConnectedFromLogicalTopologyPins(MixerData->Topology, MixerControl->NodeID, &LogicalNodesCount, LogicalNodes); 00557 00558 /* sanity check */ 00559 ASSERT(LogicalNodesCount == MixerControlDetails->cMultipleItems); 00560 ASSERT(LogicalNodesCount == MixerControl->Control.Metrics.dwReserved[0]); 00561 00562 Values = (LPMIXERCONTROLDETAILS_BOOLEAN)MixerControlDetails->paDetails; 00563 for(Index = 0; Index < LogicalNodesCount; Index++) 00564 { 00565 /* getting logical pin offset */ 00566 MMixerGetLowestLogicalTopologyPinOffsetFromArray(LogicalNodesCount, LogicalNodes, &CurLogicalPinOffset); 00567 00568 if (CurLogicalPinOffset == OldLogicalPinOffset) 00569 { 00570 /* mark index as active */ 00571 Values[Index].fValue = TRUE; 00572 } 00573 else 00574 { 00575 /* index not active */ 00576 Values[Index].fValue = FALSE; 00577 } 00578 00579 /* mark offset as consumed */ 00580 LogicalNodes[CurLogicalPinOffset] = MAXULONG; 00581 } 00582 00583 /* cleanup */ 00584 MixerContext->Free(LogicalNodes); 00585 00586 /* done */ 00587 return MM_STATUS_SUCCESS; 00588 } 00589 else if ((Flags & MIXER_GETCONTROLDETAILSF_QUERYMASK) == MIXER_GETCONTROLDETAILSF_LISTTEXT) 00590 { 00591 /* sanity check */ 00592 ASSERT(bSet == FALSE); 00593 00594 /* gets the corresponding mixer data */ 00595 MixerData = MMixerGetMixerDataByDeviceHandle(MixerContext, MixerControl->hDevice); 00596 00597 /* sanity check */ 00598 ASSERT(MixerData); 00599 ASSERT(MixerData->Topology); 00600 ASSERT(MixerData->MixerInfo == MixerInfo); 00601 00602 /* now allocate logical pin array */ 00603 Status = MMixerAllocateTopologyNodeArray(MixerContext, MixerData->Topology, &LogicalNodes); 00604 if (Status != MM_STATUS_SUCCESS) 00605 { 00606 /* no memory */ 00607 return MM_STATUS_NO_MEMORY; 00608 } 00609 00610 /* allocate connected node array */ 00611 Status = MMixerAllocateTopologyNodeArray(MixerContext, MixerData->Topology, &ConnectedNodes); 00612 if (Status != MM_STATUS_SUCCESS) 00613 { 00614 /* no memory */ 00615 MixerContext->Free(LogicalNodes); 00616 return MM_STATUS_NO_MEMORY; 00617 } 00618 00619 /* get logical pin nodes */ 00620 MMixerGetConnectedFromLogicalTopologyPins(MixerData->Topology, MixerControl->NodeID, &LogicalNodesCount, LogicalNodes); 00621 00622 /* get connected nodes */ 00623 MMixerGetNextNodesFromNodeIndex(MixerContext, MixerData->Topology, MixerControl->NodeID, TRUE, &ConnectedNodesCount, ConnectedNodes); 00624 00625 /* sanity check */ 00626 ASSERT(ConnectedNodesCount == LogicalNodesCount); 00627 ASSERT(ConnectedNodesCount == MixerControlDetails->cMultipleItems); 00628 ASSERT(ConnectedNodesCount == MixerControl->Control.Metrics.dwReserved[0]); 00629 00630 ListText = (LPMIXERCONTROLDETAILS_LISTTEXTW)MixerControlDetails->paDetails; 00631 00632 for(Index = 0; Index < ConnectedNodesCount; Index++) 00633 { 00634 /* getting logical pin offset */ 00635 MMixerGetLowestLogicalTopologyPinOffsetFromArray(LogicalNodesCount, LogicalNodes, &CurLogicalPinOffset); 00636 00637 /* get mixer line with that node */ 00638 SourceLine = MMixerGetMixerLineContainingNodeId(MixerInfo, ConnectedNodes[CurLogicalPinOffset]); 00639 00640 /* sanity check */ 00641 ASSERT(SourceLine); 00642 00643 DPRINT1("PinOffset %lu LogicalPin %lu NodeId %lu LineName %S\n", CurLogicalPinOffset, LogicalNodes[CurLogicalPinOffset], ConnectedNodes[CurLogicalPinOffset], SourceLine->Line.szName); 00644 00645 /* copy details */ 00646 ListText[Index].dwParam1 = SourceLine->Line.dwLineID; 00647 ListText[Index].dwParam2 = SourceLine->Line.dwComponentType; 00648 MixerContext->Copy(ListText[Index].szName, SourceLine->Line.szName, (wcslen(SourceLine->Line.szName) + 1) * sizeof(WCHAR)); 00649 00650 /* mark offset as consumed */ 00651 LogicalNodes[CurLogicalPinOffset] = MAXULONG; 00652 } 00653 00654 /* cleanup */ 00655 MixerContext->Free(LogicalNodes); 00656 MixerContext->Free(ConnectedNodes); 00657 00658 /* done */ 00659 return MM_STATUS_SUCCESS; 00660 } 00661 } 00662 00663 return MM_STATUS_NOT_IMPLEMENTED; 00664 } 00665 00666 MIXER_STATUS 00667 MMixerSetGetVolumeControlDetails( 00668 IN PMIXER_CONTEXT MixerContext, 00669 IN LPMIXER_INFO MixerInfo, 00670 IN ULONG NodeId, 00671 IN ULONG bSet, 00672 LPMIXERCONTROL_EXT MixerControl, 00673 IN LPMIXERCONTROLDETAILS MixerControlDetails, 00674 LPMIXERLINE_EXT MixerLine) 00675 { 00676 LPMIXERCONTROLDETAILS_UNSIGNED Input; 00677 LONG Value, Index, Channel = 0; 00678 ULONG dwValue; 00679 MIXER_STATUS Status; 00680 LPMIXERVOLUME_DATA VolumeData; 00681 00682 if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_SIGNED)) 00683 return MM_STATUS_INVALID_PARAMETER; 00684 00685 VolumeData = (LPMIXERVOLUME_DATA)MixerControl->ExtraData; 00686 if (!VolumeData) 00687 return MM_STATUS_UNSUCCESSFUL; 00688 00689 /* get input */ 00690 Input = (LPMIXERCONTROLDETAILS_UNSIGNED)MixerControlDetails->paDetails; 00691 00692 if (bSet) 00693 { 00694 /* FIXME SEH */ 00695 Value = Input->dwValue; 00696 Index = Value / VolumeData->InputSteppingDelta; 00697 00698 if (Index >= VolumeData->ValuesCount) 00699 { 00700 DPRINT1("Index %u out of bounds %u \n", Index, VolumeData->ValuesCount); 00701 return MM_STATUS_INVALID_PARAMETER; 00702 } 00703 00704 Value = VolumeData->Values[Index]; 00705 } 00706 00707 /* set control details */ 00708 if (bSet) 00709 { 00710 /* TODO */ 00711 Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value); 00712 Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value); 00713 } 00714 else 00715 { 00716 Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value); 00717 } 00718 00719 if (!bSet) 00720 { 00721 dwValue = MMixerGetVolumeControlIndex(VolumeData, (LONG)Value); 00722 /* FIXME SEH */ 00723 Input->dwValue = dwValue; 00724 } 00725 else 00726 { 00727 /* notify clients of a line change MM_MIXM_CONTROL_CHANGE with MixerControl->dwControlID */ 00728 MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->Control.dwControlID); 00729 } 00730 return Status; 00731 } 00732 00733 LPMIXER_DATA 00734 MMixerGetDataByDeviceId( 00735 IN PMIXER_LIST MixerList, 00736 IN ULONG DeviceId) 00737 { 00738 PLIST_ENTRY Entry; 00739 LPMIXER_DATA MixerData; 00740 00741 Entry = MixerList->MixerData.Flink; 00742 while(Entry != &MixerList->MixerData) 00743 { 00744 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry); 00745 if (MixerData->DeviceId == DeviceId) 00746 { 00747 return MixerData; 00748 } 00749 Entry = Entry->Flink; 00750 } 00751 return NULL; 00752 } 00753 00754 LPMIXER_DATA 00755 MMixerGetDataByDeviceName( 00756 IN PMIXER_LIST MixerList, 00757 IN LPWSTR DeviceName) 00758 { 00759 PLIST_ENTRY Entry; 00760 LPMIXER_DATA MixerData; 00761 00762 Entry = MixerList->MixerData.Flink; 00763 while(Entry != &MixerList->MixerData) 00764 { 00765 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry); 00766 if (wcsicmp(&DeviceName[2], &MixerData->DeviceName[2]) == 0) 00767 { 00768 /* found entry */ 00769 return MixerData; 00770 } 00771 Entry = Entry->Flink; 00772 } 00773 return NULL; 00774 } 00775 00776 MIXER_STATUS 00777 MMixerCreateMixerData( 00778 IN PMIXER_CONTEXT MixerContext, 00779 IN PMIXER_LIST MixerList, 00780 IN ULONG DeviceId, 00781 IN LPWSTR DeviceName, 00782 IN HANDLE hDevice, 00783 IN HANDLE hKey) 00784 { 00785 LPMIXER_DATA MixerData; 00786 00787 MixerData = (LPMIXER_DATA)MixerContext->Alloc(sizeof(MIXER_DATA)); 00788 if (!MixerData) 00789 return MM_STATUS_NO_MEMORY; 00790 00791 MixerData->DeviceId = DeviceId; 00792 MixerData->DeviceName = DeviceName; 00793 MixerData->hDevice = hDevice; 00794 MixerData->hDeviceInterfaceKey = hKey; 00795 MixerData->Topology = NULL; 00796 00797 InsertTailList(&MixerList->MixerData, &MixerData->Entry); 00798 MixerList->MixerDataCount++; 00799 return MM_STATUS_SUCCESS; 00800 } 00801 00802 MIXER_STATUS 00803 MMixerGetDeviceName( 00804 IN PMIXER_CONTEXT MixerContext, 00805 OUT LPWSTR DeviceName, 00806 IN HANDLE hKey) 00807 { 00808 LPWSTR Name; 00809 HANDLE hTemp; 00810 ULONG Length; 00811 ULONG Type; 00812 MIXER_STATUS Status; 00813 00814 Status = MixerContext->QueryKeyValue(hKey, L"FriendlyName", (PVOID*)&Name, &Length, &Type); 00815 if (Status == MM_STATUS_SUCCESS) 00816 { 00817 /* copy device name */ 00818 MixerContext->Copy(DeviceName, Name, min(wcslen(Name), MAXPNAMELEN-1) * sizeof(WCHAR)); 00819 00820 /* make sure its null terminated */ 00821 DeviceName[MAXPNAMELEN-1] = L'\0'; 00822 00823 /* free device name */ 00824 MixerContext->Free(Name); 00825 00826 /* done */ 00827 return Status; 00828 } 00829 00830 Status = MixerContext->OpenKey(hKey, L"Device Parameters", KEY_READ, &hTemp); 00831 if (Status != MM_STATUS_SUCCESS) 00832 return Status; 00833 00834 Status = MixerContext->QueryKeyValue(hTemp, L"FriendlyName", (PVOID*)&Name, &Length, &Type); 00835 if (Status == MM_STATUS_SUCCESS) 00836 { 00837 /* copy device name */ 00838 MixerContext->Copy(DeviceName, Name, min(wcslen(Name), MAXPNAMELEN-1) * sizeof(WCHAR)); 00839 00840 /* make sure its null terminated */ 00841 DeviceName[MAXPNAMELEN-1] = L'\0'; 00842 00843 /* free device name */ 00844 MixerContext->Free(Name); 00845 } 00846 00847 MixerContext->CloseKey(hTemp); 00848 return Status; 00849 } 00850 00851 VOID 00852 MMixerInitializePinConnect( 00853 IN OUT PKSPIN_CONNECT PinConnect, 00854 IN ULONG PinId) 00855 { 00856 PinConnect->Interface.Set = KSINTERFACESETID_Standard; 00857 PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; 00858 PinConnect->Interface.Flags = 0; 00859 PinConnect->Medium.Set = KSMEDIUMSETID_Standard; 00860 PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; 00861 PinConnect->Medium.Flags = 0; 00862 PinConnect->PinToHandle = NULL; 00863 PinConnect->PinId = PinId; 00864 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; 00865 PinConnect->Priority.PrioritySubClass = 1; 00866 } 00867 Generated on Mon May 28 2012 04:28:29 for ReactOS by
1.7.6.1
|