ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

sup.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.