[AUDIO-BRINGUP]

- Implement determination of the channel count for source mixer lines

svn path=/branches/audio-bringup/; revision=49960
This commit is contained in:
Johannes Anderwald 2010-12-06 02:15:33 +00:00
parent 4a8590e0d6
commit 3da0b30d8a

View file

@ -489,6 +489,132 @@ MMixerCountMixerControls(
return MM_STATUS_SUCCESS;
}
MIXER_STATUS
MMixerGetChannelCountEnhanced(
IN PMIXER_CONTEXT MixerContext,
IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
OUT PULONG MaxChannels)
{
KSPROPERTY_DESCRIPTION Description;
PKSPROPERTY_DESCRIPTION NewDescription;
PKSPROPERTY_MEMBERSHEADER Header;
ULONG BytesReturned;
KSP_NODE Request;
MIXER_STATUS Status;
/* try #1 obtain it via description */
Request.NodeId = NodeId;
Request.Reserved = 0;
Request.Property.Set = KSPROPSETID_Audio;
Request.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY;
Request.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
/* get description */
Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)&Description, sizeof(KSPROPERTY_DESCRIPTION), &BytesReturned);
if (Status == MM_STATUS_SUCCESS)
{
if (Description.DescriptionSize >= sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) && (Description.MembersListCount > 0))
{
/* allocate new description */
NewDescription = MixerContext->Alloc(Description.DescriptionSize);
if (!NewDescription)
{
/* not enough memory */
return MM_STATUS_NO_MEMORY;
}
/* get description */
Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)NewDescription, Description.DescriptionSize, &BytesReturned);
if (Status == MM_STATUS_SUCCESS)
{
/* get header */
Header = (PKSPROPERTY_MEMBERSHEADER)(NewDescription + 1);
if (Header->Flags & KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL)
{
/* found enhanced flag */
ASSERT(Header->MembersCount > 1);
/* store channel count */
*MaxChannels = Header->MembersCount;
/* free description */
MixerContext->Free(NewDescription);
/* done */
return MM_STATUS_SUCCESS;
}
}
/* free description */
MixerContext->Free(NewDescription);
}
}
/* failed to get channel count enhanced */
return MM_STATUS_UNSUCCESSFUL;
}
VOID
MMixerGetChannelCountLegacy(
IN PMIXER_CONTEXT MixerContext,
IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
OUT PULONG MaxChannels)
{
ULONG BytesReturned;
MIXER_STATUS Status;
KSNODEPROPERTY_AUDIO_CHANNEL Channel;
LONG Volume;
/* setup request */
Channel.Reserved = 0;
Channel.NodeProperty.NodeId = NodeId;
Channel.NodeProperty.Reserved = 0;
Channel.NodeProperty.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
Channel.NodeProperty.Property.Set = KSPROPSETID_Audio;
Channel.Channel = 0;
Channel.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
do
{
/* get channel volume */
Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_PROPERTY, (PVOID)&Channel, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Volume, sizeof(LONG), &BytesReturned);
if (Status != MM_STATUS_SUCCESS)
break;
/* increment channel count */
Channel.Channel++;
}while(TRUE);
/* store channel count */
*MaxChannels = Channel.Channel;
}
VOID
MMixerGetMaxChannelsForNode(
IN PMIXER_CONTEXT MixerContext,
IN LPMIXER_INFO MixerInfo,
IN ULONG NodeId,
OUT PULONG MaxChannels)
{
MIXER_STATUS Status;
/* try to get it enhanced */
Status = MMixerGetChannelCountEnhanced(MixerContext, MixerInfo, NodeId, MaxChannels);
if (Status != MM_STATUS_SUCCESS)
{
/* get it old-fashioned way */
MMixerGetChannelCountLegacy(MixerContext, MixerInfo, NodeId, MaxChannels);
}
}
MIXER_STATUS
MMixerAddMixerControlsToMixerLineByNodeIndexArray(
IN PMIXER_CONTEXT MixerContext,
@ -500,6 +626,8 @@ MMixerAddMixerControlsToMixerLineByNodeIndexArray(
{
ULONG Index, Count, bReserved;
MIXER_STATUS Status;
LPGUID NodeType;
ULONG MaxChannels;
/* store nodes array */
DstLine->NodeIds = Nodes;
@ -530,6 +658,20 @@ MMixerAddMixerControlsToMixerLineByNodeIndexArray(
/* set node status as used */
MMixerSetTopologyNodeReserved(Topology, Nodes[Index]);
/* query node type */
NodeType = MMixerGetNodeTypeFromTopology(Topology, Nodes[Index]);
if (IsEqualGUIDAligned(NodeType, &KSNODETYPE_VOLUME))
{
/* calculate maximum channel count for node */
MMixerGetMaxChannelsForNode(MixerContext, MixerInfo, Nodes[Index], &MaxChannels);
DPRINT("NodeId %lu MaxChannels %lu Line %S Id %lu\n", Nodes[Index], MaxChannels, DstLine->Line.szName, DstLine->Line.dwLineID);
/* calculate maximum channels */
DstLine->Line.cChannels = min(DstLine->Line.cChannels, MaxChannels);
}
/* now add the mixer control */
Status = MMixerAddMixerControl(MixerContext, MixerInfo, Topology, Nodes[Index], DstLine, &DstLine->LineControls[Count]);