2009-12-08 21:10:02 +00:00
/*
* COPYRIGHT : See COPYING in the top level directory
* PROJECT : ReactOS Kernel Streaming
* FILE : lib / drivers / sound / mmixer / controls . c
* PURPOSE : Mixer Control Iteration Functions
* PROGRAMMER : Johannes Anderwald
*/
# include "priv.h"
MIXER_STATUS
MMixerAddMixerControl (
IN PMIXER_CONTEXT MixerContext ,
IN LPMIXER_INFO MixerInfo ,
2010-10-15 00:20:15 +00:00
IN PTOPOLOGY Topology ,
2009-12-08 21:10:02 +00:00
IN ULONG NodeIndex ,
IN LPMIXERLINE_EXT MixerLine ,
OUT LPMIXERCONTROLW MixerControl )
{
LPGUID NodeType ;
KSP_NODE Node ;
ULONG BytesReturned ;
MIXER_STATUS Status ;
LPWSTR Name ;
/* initialize mixer control */
MixerControl - > cbStruct = sizeof ( MIXERCONTROLW ) ;
MixerControl - > dwControlID = MixerInfo - > ControlId ;
/* get node type */
2010-10-15 00:20:15 +00:00
NodeType = MMixerGetNodeTypeFromTopology ( Topology , NodeIndex ) ;
2009-12-08 21:10:02 +00:00
/* store control type */
MixerControl - > dwControlType = MMixerGetControlTypeFromTopologyNode ( NodeType ) ;
2010-10-15 00:20:15 +00:00
MixerControl - > fdwControl = MIXERCONTROL_CONTROLF_UNIFORM ; /* FIXME */
MixerControl - > cMultipleItems = 0 ; /* FIXME */
2009-12-08 21:10:02 +00:00
if ( MixerControl - > dwControlType = = MIXERCONTROL_CONTROLTYPE_MUTE )
{
MixerControl - > Bounds . dwMinimum = 0 ;
MixerControl - > Bounds . dwMaximum = 1 ;
}
else if ( MixerControl - > dwControlType = = MIXERCONTROL_CONTROLTYPE_VOLUME )
{
MixerControl - > Bounds . dwMinimum = 0 ;
MixerControl - > Bounds . dwMaximum = 0xFFFF ;
2010-10-15 00:20:15 +00:00
MixerControl - > Metrics . cSteps = 0xC0 ; /* FIXME */
2009-12-08 21:10:02 +00:00
}
/* setup request to retrieve name */
Node . NodeId = NodeIndex ;
Node . Property . Id = KSPROPERTY_TOPOLOGY_NAME ;
Node . Property . Flags = KSPROPERTY_TYPE_GET ;
Node . Property . Set = KSPROPSETID_Topology ;
Node . Reserved = 0 ;
/* get node name size */
2010-10-15 00:20:15 +00:00
Status = MixerContext - > Control ( MixerInfo - > hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Node , sizeof ( KSP_NODE ) , NULL , 0 , & BytesReturned ) ;
2009-12-08 21:10:02 +00:00
if ( Status = = MM_STATUS_MORE_ENTRIES )
{
ASSERT ( BytesReturned ! = 0 ) ;
Name = ( LPWSTR ) MixerContext - > Alloc ( BytesReturned ) ;
if ( ! Name )
{
/* not enough memory */
return MM_STATUS_NO_MEMORY ;
}
/* get node name */
2010-10-15 00:20:15 +00:00
Status = MixerContext - > Control ( MixerInfo - > hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Node , sizeof ( KSP_NODE ) , ( LPVOID ) Name , BytesReturned , & BytesReturned ) ;
2009-12-19 20:45:29 +00:00
if ( Status = = MM_STATUS_SUCCESS )
2009-12-08 21:10:02 +00:00
{
2009-12-09 16:00:28 +00:00
MixerContext - > Copy ( MixerControl - > szShortName , Name , ( min ( MIXER_SHORT_NAME_CHARS , wcslen ( Name ) + 1 ) ) * sizeof ( WCHAR ) ) ;
2009-12-08 21:10:02 +00:00
MixerControl - > szShortName [ MIXER_SHORT_NAME_CHARS - 1 ] = L ' \0 ' ;
2009-12-09 16:00:28 +00:00
MixerContext - > Copy ( MixerControl - > szName , Name , ( min ( MIXER_LONG_NAME_CHARS , wcslen ( Name ) + 1 ) ) * sizeof ( WCHAR ) ) ;
2009-12-08 21:10:02 +00:00
MixerControl - > szName [ MIXER_LONG_NAME_CHARS - 1 ] = L ' \0 ' ;
}
/* free name buffer */
MixerContext - > Free ( Name ) ;
}
MixerInfo - > ControlId + + ;
#if 0
if ( MixerControl - > dwControlType = = MIXERCONTROL_CONTROLTYPE_MUX )
{
KSNODEPROPERTY Property ;
ULONG PinId = 2 ;
/* setup the request */
RtlZeroMemory ( & Property , sizeof ( KSNODEPROPERTY ) ) ;
Property . NodeId = NodeIndex ;
Property . Property . Id = KSPROPERTY_AUDIO_MUX_SOURCE ;
Property . Property . Flags = KSPROPERTY_TYPE_SET ;
Property . Property . Set = KSPROPSETID_Audio ;
/* get node volume level info */
Status = MixerContext - > Control ( hDevice , IOCTL_KS_PROPERTY , ( PVOID ) & Property , sizeof ( KSNODEPROPERTY ) , ( PVOID ) & PinId , sizeof ( ULONG ) , & BytesReturned ) ;
DPRINT1 ( " Status %x NodeIndex %u PinId %u \n " , Status , NodeIndex , PinId ) ;
//DbgBreakPoint();
} else
# endif
if ( MixerControl - > dwControlType = = MIXERCONTROL_CONTROLTYPE_VOLUME )
{
KSNODEPROPERTY_AUDIO_CHANNEL Property ;
ULONG Length ;
PKSPROPERTY_DESCRIPTION Desc ;
PKSPROPERTY_MEMBERSHEADER Members ;
PKSPROPERTY_STEPPING_LONG Range ;
Length = sizeof ( KSPROPERTY_DESCRIPTION ) + sizeof ( KSPROPERTY_MEMBERSHEADER ) + sizeof ( KSPROPERTY_STEPPING_LONG ) ;
Desc = ( PKSPROPERTY_DESCRIPTION ) MixerContext - > Alloc ( Length ) ;
ASSERT ( Desc ) ;
/* setup the request */
RtlZeroMemory ( & Property , sizeof ( KSNODEPROPERTY_AUDIO_CHANNEL ) ) ;
Property . NodeProperty . NodeId = NodeIndex ;
Property . NodeProperty . Property . Id = KSPROPERTY_AUDIO_VOLUMELEVEL ;
Property . NodeProperty . Property . Flags = KSPROPERTY_TYPE_BASICSUPPORT ;
Property . NodeProperty . Property . Set = KSPROPSETID_Audio ;
/* get node volume level info */
2010-10-15 00:20:15 +00:00
Status = MixerContext - > Control ( MixerInfo - > hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Property , sizeof ( KSNODEPROPERTY_AUDIO_CHANNEL ) , Desc , Length , & BytesReturned ) ;
2009-12-08 21:10:02 +00:00
if ( Status = = MM_STATUS_SUCCESS )
{
LPMIXERVOLUME_DATA VolumeData ;
ULONG Steps , MaxRange , Index ;
LONG Value ;
Members = ( PKSPROPERTY_MEMBERSHEADER ) ( Desc + 1 ) ;
Range = ( PKSPROPERTY_STEPPING_LONG ) ( Members + 1 ) ;
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 ) ;
MaxRange = Range - > Bounds . UnsignedMaximum - Range - > Bounds . UnsignedMinimum ;
if ( MaxRange )
{
ASSERT ( MaxRange ) ;
VolumeData = ( LPMIXERVOLUME_DATA ) MixerContext - > Alloc ( sizeof ( MIXERVOLUME_DATA ) ) ;
if ( ! VolumeData )
return MM_STATUS_NO_MEMORY ;
Steps = MaxRange / Range - > SteppingDelta + 1 ;
/* store mixer control info there */
VolumeData - > Header . dwControlID = MixerControl - > dwControlID ;
VolumeData - > SignedMaximum = Range - > Bounds . SignedMaximum ;
VolumeData - > SignedMinimum = Range - > Bounds . SignedMinimum ;
VolumeData - > SteppingDelta = Range - > SteppingDelta ;
VolumeData - > ValuesCount = Steps ;
VolumeData - > InputSteppingDelta = 0x10000 / Steps ;
VolumeData - > Values = ( PLONG ) MixerContext - > Alloc ( sizeof ( LONG ) * Steps ) ;
if ( ! VolumeData - > Values )
{
MixerContext - > Free ( Desc ) ;
MixerContext - > Free ( VolumeData ) ;
return MM_STATUS_NO_MEMORY ;
}
Value = Range - > Bounds . SignedMinimum ;
for ( Index = 0 ; Index < Steps ; Index + + )
{
VolumeData - > Values [ Index ] = Value ;
Value + = Range - > SteppingDelta ;
}
InsertTailList ( & MixerLine - > LineControlsExtraData , & VolumeData - > Header . Entry ) ;
}
}
MixerContext - > Free ( Desc ) ;
}
DPRINT ( " Status %x Name %S \n " , Status , MixerControl - > szName ) ;
return MM_STATUS_SUCCESS ;
}
MIXER_STATUS
2010-10-15 00:20:15 +00:00
MMixerCreateDestinationLine (
2009-12-08 21:10:02 +00:00
IN PMIXER_CONTEXT MixerContext ,
2010-10-15 00:20:15 +00:00
IN LPMIXER_INFO MixerInfo ,
IN ULONG bInputMixer ,
IN LPWSTR LineName )
{
LPMIXERLINE_EXT DestinationLine ;
/* allocate a mixer destination line */
DestinationLine = ( LPMIXERLINE_EXT ) MixerContext - > Alloc ( sizeof ( MIXERLINE_EXT ) ) ;
if ( ! MixerInfo )
{
/* no memory */
return MM_STATUS_NO_MEMORY ;
}
/* initialize mixer destination line */
DestinationLine - > Line . cbStruct = sizeof ( MIXERLINEW ) ;
DestinationLine - > Line . dwSource = MAXULONG ;
2010-12-04 17:45:48 +00:00
DestinationLine - > Line . dwLineID = MixerInfo - > MixCaps . cDestinations + DESTINATION_LINE ;
2010-10-15 00:20:15 +00:00
DestinationLine - > Line . fdwLine = MIXERLINE_LINEF_ACTIVE ;
DestinationLine - > Line . dwUser = 0 ;
2010-12-04 17:45:48 +00:00
DestinationLine - > Line . dwDestination = MixerInfo - > MixCaps . cDestinations ;
2010-10-15 00:20:15 +00:00
DestinationLine - > Line . dwComponentType = ( bInputMixer = = 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN ) ;
DestinationLine - > Line . cChannels = 2 ; /* FIXME */
if ( LineName )
{
MixerContext - > Copy ( DestinationLine - > Line . szShortName , LineName , ( min ( MIXER_SHORT_NAME_CHARS , wcslen ( LineName ) + 1 ) ) * sizeof ( WCHAR ) ) ;
DestinationLine - > Line . szShortName [ MIXER_SHORT_NAME_CHARS - 1 ] = L ' \0 ' ;
MixerContext - > Copy ( DestinationLine - > Line . szName , LineName , ( min ( MIXER_LONG_NAME_CHARS , wcslen ( LineName ) + 1 ) ) * sizeof ( WCHAR ) ) ;
DestinationLine - > Line . szName [ MIXER_LONG_NAME_CHARS - 1 ] = L ' \0 ' ;
}
DestinationLine - > Line . Target . dwType = ( bInputMixer = = 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN ) ;
2010-12-04 17:45:48 +00:00
DestinationLine - > Line . Target . dwDeviceID = 0 ; //FIXME
2010-10-15 00:20:15 +00:00
DestinationLine - > Line . Target . wMid = MixerInfo - > MixCaps . wMid ;
DestinationLine - > Line . Target . wPid = MixerInfo - > MixCaps . wPid ;
DestinationLine - > Line . Target . vDriverVersion = MixerInfo - > MixCaps . vDriverVersion ;
ASSERT ( MixerInfo - > MixCaps . szPname [ MAXPNAMELEN - 1 ] = = 0 ) ;
wcscpy ( DestinationLine - > Line . Target . szPname , MixerInfo - > MixCaps . szPname ) ;
/* initialize extra line */
InitializeListHead ( & DestinationLine - > LineControlsExtraData ) ;
/* insert into mixer info */
2010-12-04 17:45:48 +00:00
InsertTailList ( & MixerInfo - > LineList , & DestinationLine - > Entry ) ;
/* increment destination count */
MixerInfo - > MixCaps . cDestinations + + ;
2010-10-15 00:20:15 +00:00
/* done */
return MM_STATUS_SUCCESS ;
}
MIXER_STATUS
MMixerGetPinName (
IN PMIXER_CONTEXT MixerContext ,
IN LPMIXER_INFO MixerInfo ,
2009-12-08 21:10:02 +00:00
IN ULONG PinId ,
2010-10-15 00:20:15 +00:00
IN OUT LPWSTR * OutBuffer )
2009-12-08 21:10:02 +00:00
{
KSP_PIN Pin ;
2010-10-15 00:20:15 +00:00
ULONG BytesReturned ;
LPWSTR Buffer ;
MIXER_STATUS Status ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* prepare pin */
Pin . PinId = PinId ;
Pin . Reserved = 0 ;
Pin . Property . Flags = KSPROPERTY_TYPE_GET ;
Pin . Property . Set = KSPROPSETID_Pin ;
Pin . Property . Id = KSPROPERTY_PIN_NAME ;
/* try get pin name size */
Status = MixerContext - > Control ( MixerInfo - > hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Pin , sizeof ( KSP_PIN ) , NULL , 0 , & BytesReturned ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* check if buffer overflowed */
if ( Status = = MM_STATUS_MORE_ENTRIES )
{
/* allocate buffer */
Buffer = ( LPWSTR ) MixerContext - > Alloc ( BytesReturned ) ;
if ( ! Buffer )
{
/* out of memory */
2009-12-08 21:10:02 +00:00
return MM_STATUS_NO_MEMORY ;
2010-10-15 00:20:15 +00:00
}
/* try get pin name */
Status = MixerContext - > Control ( MixerInfo - > hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Pin , sizeof ( KSP_PIN ) , ( PVOID ) Buffer , BytesReturned , & BytesReturned ) ;
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to get pin name */
MixerContext - > Free ( ( PVOID ) Buffer ) ;
return Status ;
}
/* successfully obtained pin name */
* OutBuffer = Buffer ;
return MM_STATUS_SUCCESS ;
}
/* failed to get pin name */
return Status ;
}
MIXER_STATUS
MMixerBuildMixerDestinationLine (
IN PMIXER_CONTEXT MixerContext ,
IN OUT LPMIXER_INFO MixerInfo ,
IN ULONG PinId ,
IN ULONG bInput )
{
LPWSTR PinName ;
MIXER_STATUS Status ;
/* try get pin name */
Status = MMixerGetPinName ( MixerContext , MixerInfo , PinId , & PinName ) ;
if ( Status = = MM_STATUS_SUCCESS )
{
/* create mixer destination line */
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
Status = MMixerCreateDestinationLine ( MixerContext , MixerInfo , bInput , PinName ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* free pin name */
MixerContext - > Free ( PinName ) ;
2009-12-08 21:10:02 +00:00
}
else
{
2010-10-15 00:20:15 +00:00
/* create mixer destination line unlocalized */
Status = MMixerCreateDestinationLine ( MixerContext , MixerInfo , bInput , L " No Name " ) ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
return Status ;
}
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
MIXER_STATUS
MMixerBuildTopology (
IN PMIXER_CONTEXT MixerContext ,
IN LPMIXER_DATA MixerData ,
OUT PTOPOLOGY * OutTopology )
{
ULONG PinsCount ;
PKSMULTIPLE_ITEM NodeTypes = NULL ;
PKSMULTIPLE_ITEM NodeConnections = NULL ;
MIXER_STATUS Status ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
if ( MixerData - > Topology )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* re-use existing topology */
* OutTopology = MixerData - > Topology ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
return MM_STATUS_SUCCESS ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* get connected filter pin count */
PinsCount = MMixerGetFilterPinCount ( MixerContext , MixerData - > hDevice ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
if ( ! PinsCount )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* referenced filter does not have any pins */
return MM_STATUS_UNSUCCESSFUL ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* get topology node types */
Status = MMixerGetFilterTopologyProperty ( MixerContext , MixerData - > hDevice , KSPROPERTY_TOPOLOGY_NODES , & NodeTypes ) ;
2009-12-08 21:10:02 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
2010-10-15 00:20:15 +00:00
/* failed to get topology node types */
2009-12-08 21:10:02 +00:00
return Status ;
}
2010-10-15 00:20:15 +00:00
/* get topology connections */
Status = MMixerGetFilterTopologyProperty ( MixerContext , MixerData - > hDevice , KSPROPERTY_TOPOLOGY_CONNECTIONS , & NodeConnections ) ;
if ( Status ! = MM_STATUS_SUCCESS )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* failed to get topology connections */
MixerContext - > Free ( NodeTypes ) ;
return Status ;
}
2009-12-13 11:32:44 +00:00
2010-10-15 00:20:15 +00:00
/* create a topology */
Status = MMixerCreateTopology ( MixerContext , PinsCount , NodeConnections , NodeTypes , OutTopology ) ;
/* free node types & connections */
MixerContext - > Free ( NodeConnections ) ;
MixerContext - > Free ( NodeTypes ) ;
if ( Status = = MM_STATUS_SUCCESS )
{
/* store topology object */
MixerData - > Topology = * OutTopology ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* done */
return Status ;
}
MIXER_STATUS
MMixerCountMixerControls (
IN PMIXER_CONTEXT MixerContext ,
IN PTOPOLOGY Topology ,
IN ULONG PinId ,
2010-12-04 17:45:48 +00:00
IN ULONG bInputMixer ,
2010-10-15 00:20:15 +00:00
IN ULONG bUpStream ,
OUT PULONG OutNodesCount ,
OUT PULONG OutNodes ,
OUT PULONG OutLineTerminator )
{
PULONG Nodes ;
ULONG NodesCount , NodeIndex , Count , bTerminator ;
MIXER_STATUS Status ;
/* allocate an array to store all nodes which are upstream of this pin */
Status = MMixerAllocateTopologyNodeArray ( MixerContext , Topology , & Nodes ) ;
if ( Status ! = MM_STATUS_SUCCESS )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* out of memory */
return STATUS_NO_MEMORY ;
}
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* mark result array as zero */
* OutNodesCount = 0 ;
/* get next nodes */
MMixerGetNextNodesFromPinIndex ( MixerContext , Topology , PinId , bUpStream , & NodesCount , Nodes ) ;
/* assume no topology split before getting line terminator */
ASSERT ( NodesCount = = 1 ) ;
/* get first node */
NodeIndex = Nodes [ 0 ] ;
Count = 0 ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
do
{
/* check if the node is a terminator */
MMixerIsNodeTerminator ( Topology , NodeIndex , & bTerminator ) ;
if ( bTerminator )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* found terminator */
2010-12-04 17:45:48 +00:00
if ( bInputMixer )
{
/* add mux source for source destination line */
OutNodes [ Count ] = NodeIndex ;
Count + + ;
}
2010-10-15 00:20:15 +00:00
break ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* store node id */
OutNodes [ Count ] = NodeIndex ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* increment node count */
Count + + ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* get next nodes upstream */
MMixerGetNextNodesFromNodeIndex ( MixerContext , Topology , NodeIndex , bUpStream , & NodesCount , Nodes ) ;
/* assume there is a node connected */
ASSERT ( NodesCount ! = 0 ) ;
ASSERT ( NodesCount = = 1 ) ;
/* use first index */
NodeIndex = Nodes [ 0 ] ;
} while ( TRUE ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* free node index */
2009-12-08 21:10:02 +00:00
MixerContext - > Free ( Nodes ) ;
2010-10-15 00:20:15 +00:00
/* store nodes count */
* OutNodesCount = Count ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* store line terminator */
* OutLineTerminator = NodeIndex ;
/* done */
return MM_STATUS_SUCCESS ;
}
MIXER_STATUS
MMixerAddMixerControlsToMixerLineByNodeIndexArray (
IN PMIXER_CONTEXT MixerContext ,
IN LPMIXER_INFO MixerInfo ,
IN PTOPOLOGY Topology ,
IN OUT LPMIXERLINE_EXT DstLine ,
IN ULONG NodesCount ,
IN PULONG Nodes )
{
ULONG Index , Count , bReserved ;
MIXER_STATUS Status ;
/* store nodes array */
DstLine - > NodeIds = Nodes ;
/* allocate MIXERCONTROLSW array */
DstLine - > LineControls = MixerContext - > Alloc ( NodesCount * sizeof ( MIXERCONTROLW ) ) ;
if ( ! DstLine - > LineControls )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* out of memory */
return MM_STATUS_NO_MEMORY ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* initialize control count */
Count = 0 ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
for ( Index = 0 ; Index < NodesCount ; Index + + )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* check if the node has already been reserved to a line */
MMixerIsTopologyNodeReserved ( Topology , Nodes [ Index ] , & bReserved ) ;
2010-12-04 17:45:48 +00:00
#if 0 /* MS lies */
2010-10-15 00:20:15 +00:00
if ( bReserved )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* node is already used, skip it */
continue ;
}
2010-12-04 17:45:48 +00:00
# endif
2010-10-15 00:20:15 +00:00
/* set node status as used */
MMixerSetTopologyNodeReserved ( Topology , Nodes [ Index ] ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* now add the mixer control */
Status = MMixerAddMixerControl ( MixerContext , MixerInfo , Topology , Nodes [ Index ] , DstLine , & DstLine - > LineControls [ Count ] ) ;
if ( Status = = MM_STATUS_SUCCESS )
{
/* increment control count */
Count + + ;
2009-12-08 21:10:02 +00:00
}
}
2010-10-15 00:20:15 +00:00
/* store control count */
DstLine - > Line . cControls = Count ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* done */
2009-12-08 21:10:02 +00:00
return MM_STATUS_SUCCESS ;
}
MIXER_STATUS
2010-10-15 00:20:15 +00:00
MMixerBuildMixerSourceLine (
2009-12-08 21:10:02 +00:00
IN PMIXER_CONTEXT MixerContext ,
2010-10-15 00:20:15 +00:00
IN OUT LPMIXER_INFO MixerInfo ,
IN PTOPOLOGY Topology ,
IN ULONG PinId ,
IN ULONG NodesCount ,
IN PULONG Nodes ,
2010-12-04 17:45:48 +00:00
IN ULONG DestinationLineID ,
2010-10-15 00:20:15 +00:00
OUT LPMIXERLINE_EXT * OutSrcLine )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
LPMIXERLINE_EXT SrcLine , DstLine ;
LPWSTR PinName ;
MIXER_STATUS Status ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* construct source line */
SrcLine = ( LPMIXERLINE_EXT ) MixerContext - > Alloc ( sizeof ( MIXERLINE_EXT ) ) ;
if ( ! SrcLine )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* no memory */
2009-12-08 21:10:02 +00:00
return MM_STATUS_NO_MEMORY ;
}
2010-10-15 00:20:15 +00:00
/* get destination line */
2010-12-04 17:45:48 +00:00
DstLine = MMixerGetSourceMixerLineByLineId ( MixerInfo , DestinationLineID ) ;
2010-10-15 00:20:15 +00:00
ASSERT ( DstLine ) ;
2009-12-11 14:01:39 +00:00
2010-10-15 00:20:15 +00:00
/* initialize mixer src line */
SrcLine - > hDevice = MixerInfo - > hMixer ;
SrcLine - > PinId = PinId ;
SrcLine - > NodeIds = Nodes ;
/* initialize mixer line */
SrcLine - > Line . cbStruct = sizeof ( MIXERLINEW ) ;
SrcLine - > Line . dwDestination = 0 ;
SrcLine - > Line . dwSource = DstLine - > Line . cConnections ;
2010-12-04 18:53:51 +00:00
SrcLine - > Line . dwLineID = ( DstLine - > Line . cConnections * SOURCE_LINE ) + ( MixerInfo - > MixCaps . cDestinations - 1 ) ;
2010-10-15 00:20:15 +00:00
SrcLine - > Line . fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE ;
SrcLine - > Line . dwUser = 0 ;
SrcLine - > Line . cChannels = DstLine - > Line . cChannels ;
SrcLine - > Line . cConnections = 0 ;
SrcLine - > Line . Target . dwType = 1 ;
SrcLine - > Line . Target . dwDeviceID = DstLine - > Line . Target . dwDeviceID ;
SrcLine - > Line . Target . wMid = MixerInfo - > MixCaps . wMid ;
SrcLine - > Line . Target . wPid = MixerInfo - > MixCaps . wPid ;
SrcLine - > Line . Target . vDriverVersion = MixerInfo - > MixCaps . vDriverVersion ;
InitializeListHead ( & SrcLine - > LineControlsExtraData ) ;
/* copy name */
ASSERT ( MixerInfo - > MixCaps . szPname [ MAXPNAMELEN - 1 ] = = L ' \0 ' ) ;
wcscpy ( SrcLine - > Line . Target . szPname , MixerInfo - > MixCaps . szPname ) ;
/* get pin name */
Status = MMixerGetPinName ( MixerContext , MixerInfo , PinId , & PinName ) ;
if ( Status = = MM_STATUS_SUCCESS )
2009-12-11 14:01:39 +00:00
{
2010-10-15 00:20:15 +00:00
/* store pin name as line name */
MixerContext - > Copy ( SrcLine - > Line . szShortName , PinName , ( min ( MIXER_SHORT_NAME_CHARS , wcslen ( PinName ) + 1 ) ) * sizeof ( WCHAR ) ) ;
SrcLine - > Line . szShortName [ MIXER_SHORT_NAME_CHARS - 1 ] = L ' \0 ' ;
2009-12-19 21:44:39 +00:00
2010-10-15 00:20:15 +00:00
MixerContext - > Copy ( SrcLine - > Line . szName , PinName , ( min ( MIXER_LONG_NAME_CHARS , wcslen ( PinName ) + 1 ) ) * sizeof ( WCHAR ) ) ;
SrcLine - > Line . szName [ MIXER_LONG_NAME_CHARS - 1 ] = L ' \0 ' ;
2009-12-19 21:44:39 +00:00
2010-10-15 00:20:15 +00:00
/* free pin name buffer */
MixerContext - > Free ( PinName ) ;
2009-12-11 14:01:39 +00:00
}
2010-10-15 00:20:15 +00:00
/* add the controls to mixer line */
Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray ( MixerContext , MixerInfo , Topology , SrcLine , NodesCount , Nodes ) ;
if ( Status ! = MM_STATUS_SUCCESS )
2009-12-11 14:01:39 +00:00
{
2010-10-15 00:20:15 +00:00
/* failed */
return Status ;
2009-12-11 14:01:39 +00:00
}
2010-10-15 00:20:15 +00:00
/* store result */
* OutSrcLine = SrcLine ;
2009-12-08 21:10:02 +00:00
return MM_STATUS_SUCCESS ;
}
MIXER_STATUS
2010-10-15 00:20:15 +00:00
MMixerAddMixerSourceLines (
2009-12-08 21:10:02 +00:00
IN PMIXER_CONTEXT MixerContext ,
2010-10-15 00:20:15 +00:00
IN OUT LPMIXER_INFO MixerInfo ,
IN PTOPOLOGY Topology ,
2010-12-04 17:45:48 +00:00
IN ULONG DestinationLineID ,
2010-10-15 00:20:15 +00:00
IN ULONG LineTerminator )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
PULONG AllNodes , AllPins , AllPinNodes ;
ULONG AllNodesCount , AllPinsCount , AllPinNodesCount ;
ULONG Index , SubIndex , PinId , CurNode , bConnected ;
2009-12-08 21:10:02 +00:00
MIXER_STATUS Status ;
2010-10-15 00:20:15 +00:00
LPMIXERLINE_EXT DstLine , SrcLine ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* get destination line */
2010-12-04 17:45:48 +00:00
DstLine = MMixerGetSourceMixerLineByLineId ( MixerInfo , DestinationLineID ) ;
2010-10-15 00:20:15 +00:00
ASSERT ( DstLine ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* allocate an array to store all nodes which are upstream of the line terminator */
Status = MMixerAllocateTopologyNodeArray ( MixerContext , Topology , & AllNodes ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* check for success */
if ( Status ! = MM_STATUS_SUCCESS )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* out of memory */
return MM_STATUS_NO_MEMORY ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* allocate an array to store all nodes which are downstream of a particular pin */
Status = MMixerAllocateTopologyNodeArray ( MixerContext , Topology , & AllPinNodes ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* allocate an array to store all pins which are upstream of this pin */
Status = MMixerAllocateTopologyPinArray ( MixerContext , Topology , & AllPins ) ;
/* check for success */
if ( Status ! = MM_STATUS_SUCCESS )
{
/* out of memory */
MixerContext - > Free ( AllNodes ) ;
return MM_STATUS_NO_MEMORY ;
}
/* get all nodes which indirectly / directly connect to this node */
AllNodesCount = 0 ;
MMixerGetAllUpOrDownstreamNodesFromNodeIndex ( MixerContext , Topology , LineTerminator , TRUE , & AllNodesCount , AllNodes ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* get all pins which indirectly / directly connect to this node */
2010-10-16 12:36:21 +00:00
AllPinsCount = 0 ;
2010-10-15 00:20:15 +00:00
MMixerGetAllUpOrDownstreamPinsFromNodeIndex ( MixerContext , Topology , LineTerminator , TRUE , & AllPinsCount , AllPins ) ;
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
DPRINT1 ( " LineTerminator %lu \n " , LineTerminator ) ;
DPRINT1 ( " PinCount %lu \n " , AllPinsCount ) ;
DPRINT1 ( " AllNodesCount %lu \n " , AllNodesCount ) ;
2010-10-15 00:20:15 +00:00
/* now construct the source lines which are attached to the destination line */
Index = AllPinsCount ;
do
{
/* get current pin id */
PinId = AllPins [ Index - 1 ] ;
/* reset nodes count */
AllPinNodesCount = 0 ;
/* now scan all nodes and add them to AllPinNodes array when they are connected to this pin */
for ( SubIndex = 0 ; SubIndex < AllNodesCount ; SubIndex + + )
{
/* get current node index */
CurNode = AllNodes [ SubIndex ] ;
if ( CurNode ! = MAXULONG & & CurNode ! = LineTerminator )
{
/* check if that node is connected in some way to the current pin */
Status = MMixerIsNodeConnectedToPin ( MixerContext , Topology , CurNode , PinId , TRUE , & bConnected ) ;
if ( Status ! = MM_STATUS_SUCCESS )
break ;
if ( bConnected )
{
/* it is connected */
AllPinNodes [ AllPinNodesCount ] = CurNode ;
AllPinNodesCount + + ;
/* clear current index */
AllNodes [ SubIndex ] = MAXULONG ;
}
}
}
/* decrement pin index */
Index - - ;
if ( AllPinNodesCount )
{
2010-12-04 17:45:48 +00:00
# ifdef MMIXER_DEBUG
ULONG TempIndex ;
# endif
2010-10-15 00:20:15 +00:00
/* now build the mixer source line */
2010-12-04 17:45:48 +00:00
Status = MMixerBuildMixerSourceLine ( MixerContext , MixerInfo , Topology , PinId , AllPinNodesCount , AllPinNodes , DestinationLineID , & SrcLine ) ;
2010-10-15 00:20:15 +00:00
if ( Status = = MM_STATUS_SUCCESS )
{
/* insert into line list */
InsertTailList ( & MixerInfo - > LineList , & SrcLine - > Entry ) ;
/* increment destination line count */
DstLine - > Line . cConnections + + ;
2010-12-04 17:45:48 +00:00
# ifdef MMIXER_DEBUG
DPRINT1 ( " Adding PinId %lu AllPinNodesCount %lu to DestinationLine %lu \n " , PinId , AllPinNodesCount , DestinationLineID ) ;
for ( TempIndex = 0 ; TempIndex < AllPinNodesCount ; TempIndex + + )
DPRINT1 ( " NodeIndex %lu \n " , AllPinNodes [ TempIndex ] ) ;
# endif
2010-10-15 00:20:15 +00:00
}
}
2010-12-04 17:45:48 +00:00
else
{
# ifdef MMIXER_DEBUG
DPRINT1 ( " Discarding DestinationLineID %lu PinId %lu NO NODES! \n " , DestinationLineID , PinId ) ;
# endif
}
2010-10-15 00:20:15 +00:00
} while ( Index ! = 0 ) ;
return MM_STATUS_SUCCESS ;
}
2009-12-08 21:10:02 +00:00
MIXER_STATUS
2010-10-15 00:20:15 +00:00
MMixerAddMixerControlsToDestinationLine (
2009-12-08 21:10:02 +00:00
IN PMIXER_CONTEXT MixerContext ,
IN OUT LPMIXER_INFO MixerInfo ,
2010-10-15 00:20:15 +00:00
IN PTOPOLOGY Topology ,
IN ULONG PinId ,
IN ULONG bInput ,
2010-12-04 17:45:48 +00:00
IN ULONG DestinationLineId ,
2010-10-15 00:20:15 +00:00
OUT PULONG OutLineTerminator )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
PULONG Nodes ;
ULONG NodesCount , LineTerminator ;
MIXER_STATUS Status ;
LPMIXERLINE_EXT DstLine ;
/* allocate nodes index array */
Status = MMixerAllocateTopologyNodeArray ( MixerContext , Topology , & Nodes ) ;
/* check for success */
if ( Status ! = MM_STATUS_SUCCESS )
{
/* out of memory */
return MM_STATUS_NO_MEMORY ;
}
/* get all destination line controls */
2010-12-04 17:45:48 +00:00
Status = MMixerCountMixerControls ( MixerContext , Topology , PinId , bInput , TRUE , & NodesCount , Nodes , & LineTerminator ) ;
2010-10-15 00:20:15 +00:00
/* check for success */
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to count controls */
MixerContext - > Free ( Nodes ) ;
return Status ;
}
/* get destination mixer line */
2010-12-04 17:45:48 +00:00
DstLine = MMixerGetSourceMixerLineByLineId ( MixerInfo , DestinationLineId ) ;
2010-10-15 00:20:15 +00:00
/* sanity check */
ASSERT ( DstLine ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
if ( NodesCount > 0 )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* add all nodes as mixer controls to the destination line */
Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray ( MixerContext , MixerInfo , Topology , DstLine , NodesCount , Nodes ) ;
if ( Status ! = MM_STATUS_SUCCESS )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* failed to add controls */
MixerContext - > Free ( Nodes ) ;
return Status ;
2009-12-08 21:10:02 +00:00
}
}
2010-10-15 00:20:15 +00:00
/* store result */
* OutLineTerminator = LineTerminator ;
/* return result */
return Status ;
}
2009-12-08 21:10:02 +00:00
2010-10-17 21:15:21 +00:00
VOID
MMixerApplyOutputFilterHack (
IN PMIXER_CONTEXT MixerContext ,
IN LPMIXER_DATA MixerData ,
IN OUT PULONG PinsCount ,
IN OUT PULONG Pins )
{
ULONG Count = 0 , Index ;
MIXER_STATUS Status ;
PKSPIN_PHYSICALCONNECTION Connection ;
for ( Index = 0 ; Index < * PinsCount ; Index + + )
{
/* check if it has a physical connection */
Status = MMixerGetPhysicalConnection ( MixerContext , MixerData - > hDevice , Pins [ Index ] , & Connection ) ;
if ( Status = = MM_STATUS_SUCCESS )
{
/* remove pin */
MixerContext - > Copy ( & Pins [ Index ] , & Pins [ Index + 1 ] , ( * PinsCount - ( Index + 1 ) ) * sizeof ( ULONG ) ) ;
/* free physical connection */
MixerContext - > Free ( Connection ) ;
/* decrement index */
Index - - ;
/* decrement pin count */
( * PinsCount ) - - ;
}
else
{
/* simple pin */
Count + + ;
}
}
/* store result */
* PinsCount = Count ;
}
2009-12-08 21:10:02 +00:00
MIXER_STATUS
MMixerHandlePhysicalConnection (
IN PMIXER_CONTEXT MixerContext ,
2009-12-18 10:25:41 +00:00
IN PMIXER_LIST MixerList ,
2010-10-15 00:20:15 +00:00
IN LPMIXER_DATA MixerData ,
2009-12-08 21:10:02 +00:00
IN OUT LPMIXER_INFO MixerInfo ,
IN ULONG bInput ,
IN PKSPIN_PHYSICALCONNECTION OutConnection )
{
MIXER_STATUS Status ;
2010-12-04 17:45:48 +00:00
ULONG PinsCount , LineTerminator , DestinationLineID ;
2010-10-15 00:20:15 +00:00
PULONG Pins ;
PTOPOLOGY Topology ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* first try to open the connected filter */
2009-12-18 10:25:41 +00:00
OutConnection - > SymbolicLinkName [ 1 ] = L ' \\ ' ;
MixerData = MMixerGetDataByDeviceName ( MixerList , OutConnection - > SymbolicLinkName ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* check if the linked connection is found */
if ( ! MixerData )
{
/* filter references invalid physical connection */
return MM_STATUS_UNSUCCESSFUL ;
}
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
DPRINT1 ( " Name %S, Pin %lu bInput %lu \n " , OutConnection - > SymbolicLinkName , OutConnection - > Pin , bInput ) ;
if ( MixerInfo - > hMixer ! = NULL )
{
/* dont replace mixer destination handles */
DPRINT1 ( " MixerInfo hDevice %p MixerData hDevice %p \n " , MixerInfo - > hMixer , MixerData - > hDevice ) ;
ASSERT ( MixerInfo - > hMixer = = MixerData - > hDevice ) ;
}
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* store connected mixer handle */
MixerInfo - > hMixer = MixerData - > hDevice ;
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
if ( MixerData - > Topology = = NULL )
{
/* construct new topology */
Status = MMixerBuildTopology ( MixerContext , MixerData , & Topology ) ;
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to create topology */
return Status ;
}
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
/* store topology */
MixerData - > Topology = Topology ;
}
else
2009-12-08 21:10:02 +00:00
{
2010-12-04 17:45:48 +00:00
/* re-use existing topology */
Topology = MixerData - > Topology ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* allocate pin index array which will hold all referenced pins */
Status = MMixerAllocateTopologyPinArray ( MixerContext , Topology , & Pins ) ;
ASSERT ( Status = = MM_STATUS_SUCCESS ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
if ( ! bInput )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* the mixer is an output mixer
* find end pin of the node path
*/
2010-10-16 12:36:21 +00:00
PinsCount = 0 ;
2010-10-15 00:20:15 +00:00
Status = MMixerGetAllUpOrDownstreamPinsFromPinIndex ( MixerContext , Topology , OutConnection - > Pin , FALSE , & PinsCount , Pins ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* check for success */
if ( Status ! = MM_STATUS_SUCCESS )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* failed to get end pin */
MixerContext - > Free ( Pins ) ;
//MMixerFreeTopology(Topology);
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* return error code */
return Status ;
}
2010-10-17 21:15:21 +00:00
/* HACK:
* some topologies do not have strict boundaries
* WorkArround : remove all pin ids which have a physical connection
* because bridge pins may belong to different render paths
*/
MMixerApplyOutputFilterHack ( MixerContext , MixerData , & PinsCount , Pins ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* sanity checks */
ASSERT ( PinsCount ! = 0 ) ;
2010-10-17 21:15:21 +00:00
ASSERT ( PinsCount = = 1 ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* create destination line */
Status = MMixerBuildMixerDestinationLine ( MixerContext , MixerInfo , Pins [ 0 ] , bInput ) ;
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
/* calculate destination line id */
DestinationLineID = ( DESTINATION_LINE + MixerInfo - > MixCaps . cDestinations - 1 ) ;
2010-10-15 00:20:15 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
2010-12-04 17:45:48 +00:00
/* failed to build destination line */
2010-10-15 00:20:15 +00:00
MixerContext - > Free ( Pins ) ;
/* return error code */
return Status ;
}
/* add mixer controls to destination line */
2010-12-04 17:45:48 +00:00
Status = MMixerAddMixerControlsToDestinationLine ( MixerContext , MixerInfo , Topology , Pins [ 0 ] , bInput , DestinationLineID , & LineTerminator ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
if ( Status = = MM_STATUS_SUCCESS )
{
/* now add the rest of the source lines */
2010-12-04 17:45:48 +00:00
Status = MMixerAddMixerSourceLines ( MixerContext , MixerInfo , Topology , DestinationLineID , LineTerminator ) ;
2010-10-15 00:20:15 +00:00
}
}
else
{
2010-12-04 17:45:48 +00:00
/* calculate destination line id */
DestinationLineID = ( DESTINATION_LINE + MixerInfo - > MixCaps . cDestinations - 1 ) ;
/* add mixer controls */
Status = MMixerAddMixerControlsToDestinationLine ( MixerContext , MixerInfo , Topology , OutConnection - > Pin , bInput , DestinationLineID , & LineTerminator ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
if ( Status = = MM_STATUS_SUCCESS )
{
/* now add the rest of the source lines */
2010-12-04 17:45:48 +00:00
Status = MMixerAddMixerSourceLines ( MixerContext , MixerInfo , Topology , DestinationLineID , LineTerminator ) ;
2009-12-08 21:10:02 +00:00
}
}
return Status ;
}
MIXER_STATUS
MMixerInitializeFilter (
IN PMIXER_CONTEXT MixerContext ,
2009-12-09 09:51:39 +00:00
IN PMIXER_LIST MixerList ,
2009-12-18 10:25:41 +00:00
IN LPMIXER_DATA MixerData ,
2010-12-04 17:45:48 +00:00
IN LPMIXER_INFO MixerInfo ,
2010-10-15 00:20:15 +00:00
IN PTOPOLOGY Topology ,
2009-12-08 21:10:02 +00:00
IN ULONG NodeIndex ,
2010-12-04 17:45:48 +00:00
IN ULONG bInputMixer ,
IN OUT LPMIXER_INFO * OutMixerInfo )
2009-12-08 21:10:02 +00:00
{
2010-12-04 17:45:48 +00:00
2009-12-08 21:10:02 +00:00
MIXER_STATUS Status ;
PKSPIN_PHYSICALCONNECTION OutConnection ;
ULONG * Pins ;
2010-10-15 00:20:15 +00:00
ULONG PinsFound ;
2010-12-04 17:45:48 +00:00
ULONG NewMixerInfo = FALSE ;
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
if ( MixerInfo = = NULL )
2009-12-08 21:10:02 +00:00
{
2010-12-04 17:45:48 +00:00
/* allocate a mixer info struct */
MixerInfo = ( LPMIXER_INFO ) MixerContext - > Alloc ( sizeof ( MIXER_INFO ) ) ;
if ( ! MixerInfo )
{
/* no memory */
return MM_STATUS_NO_MEMORY ;
}
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
/* new mixer info */
NewMixerInfo = TRUE ;
/* intialize mixer caps */
MixerInfo - > MixCaps . wMid = MM_MICROSOFT ; /* FIXME */
MixerInfo - > MixCaps . wPid = MM_PID_UNMAPPED ; /* FIXME */
MixerInfo - > MixCaps . vDriverVersion = 1 ; /* FIXME */
MixerInfo - > MixCaps . fdwSupport = 0 ;
MixerInfo - > MixCaps . cDestinations = 0 ;
2009-12-18 10:25:41 +00:00
2010-12-04 17:45:48 +00:00
/* get mixer name */
MMixerGetDeviceName ( MixerContext , MixerInfo - > MixCaps . szPname , MixerData - > hDeviceInterfaceKey ) ;
/* initialize line list */
InitializeListHead ( & MixerInfo - > LineList ) ;
InitializeListHead ( & MixerInfo - > EventList ) ;
}
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
/* store mixer info */
* OutMixerInfo = MixerInfo ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* now allocate an array which will receive the indices of the pin
* which has a ADC / DAC nodetype in its path
*/
Status = MMixerAllocateTopologyPinArray ( MixerContext , Topology , & Pins ) ;
ASSERT ( Status = = MM_STATUS_SUCCESS ) ;
2010-06-12 10:21:03 +00:00
2010-10-15 00:20:15 +00:00
PinsFound = 0 ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* now get all sink / source pins, which are attached to the ADC / DAC node
* For sink pins ( wave out ) search up stream
* For source pins ( wave in ) search down stream
* The search direction is always the opposite of the current mixer type
*/
2010-10-16 12:36:21 +00:00
PinsFound = 0 ;
2010-10-15 00:20:15 +00:00
MMixerGetAllUpOrDownstreamPinsFromNodeIndex ( MixerContext , Topology , NodeIndex , ! bInputMixer , & PinsFound , Pins ) ;
2009-12-08 21:10:02 +00:00
2010-12-04 17:45:48 +00:00
/* if there is no pin found, we have a broken topology */
2010-10-15 00:20:15 +00:00
ASSERT ( PinsFound ! = 0 ) ;
2009-12-11 14:01:39 +00:00
2010-10-15 00:20:15 +00:00
/* now create a wave info struct */
Status = MMixerInitializeWaveInfo ( MixerContext , MixerList , MixerData , MixerInfo - > MixCaps . szPname , bInputMixer , PinsFound , Pins ) ;
if ( Status ! = MM_STATUS_SUCCESS )
2009-12-11 14:01:39 +00:00
{
2010-10-15 00:20:15 +00:00
/* failed to create wave info struct */
MixerContext - > Free ( MixerInfo ) ;
MixerContext - > Free ( Pins ) ;
return Status ;
}
2009-12-11 14:01:39 +00:00
2010-10-15 00:20:15 +00:00
if ( bInputMixer )
{
/* pre create the mixer destination line for input mixers */
Status = MMixerBuildMixerDestinationLine ( MixerContext , MixerInfo , Pins [ 0 ] , bInputMixer ) ;
2009-12-11 14:01:39 +00:00
2010-10-15 00:20:15 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to create mixer destination line */
return Status ;
2009-12-11 14:01:39 +00:00
}
}
2009-12-20 00:55:55 +00:00
2010-10-15 00:20:15 +00:00
/* now get the bridge pin which is at the end of node path
* For sink pins ( wave out ) search down stream
* For source pins ( wave in ) search up stream
*/
MixerContext - > Free ( Pins ) ;
Status = MMixerAllocateTopologyPinArray ( MixerContext , Topology , & Pins ) ;
ASSERT ( Status = = MM_STATUS_SUCCESS ) ;
2009-12-11 14:01:39 +00:00
2010-10-16 12:36:21 +00:00
PinsFound = 0 ;
2010-10-15 00:20:15 +00:00
MMixerGetAllUpOrDownstreamPinsFromNodeIndex ( MixerContext , Topology , NodeIndex , bInputMixer , & PinsFound , Pins ) ;
2009-12-11 14:01:39 +00:00
2010-10-15 00:20:15 +00:00
/* if there is no pin found, we have a broken topology */
ASSERT ( PinsFound ! = 0 ) ;
2009-12-11 14:01:39 +00:00
2010-10-15 00:20:15 +00:00
/* there should be exactly one bridge pin */
ASSERT ( PinsFound = = 1 ) ;
2009-12-11 14:01:39 +00:00
2010-10-15 00:20:15 +00:00
DPRINT ( " BridgePin %lu bInputMixer %lu \n " , Pins [ 0 ] , bInputMixer ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* does the pin have a physical connection */
Status = MMixerGetPhysicalConnection ( MixerContext , MixerData - > hDevice , Pins [ 0 ] , & OutConnection ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
if ( Status = = MM_STATUS_SUCCESS )
{
/* topology on the topoloy filter */
Status = MMixerHandlePhysicalConnection ( MixerContext , MixerList , MixerData , MixerInfo , bInputMixer , OutConnection ) ;
2009-12-10 12:27:16 +00:00
2010-10-15 00:20:15 +00:00
/* free physical connection data */
MixerContext - > Free ( OutConnection ) ;
}
else
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* FIXME
* handle drivers which expose their topology on the same filter
*/
ASSERT ( 0 ) ;
2010-12-04 17:45:48 +00:00
MixerInfo - > hMixer = MixerData - > hDevice ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* free pins */
2009-12-08 21:10:02 +00:00
MixerContext - > Free ( Pins ) ;
2010-12-04 17:45:48 +00:00
if ( NewMixerInfo )
2009-12-10 12:27:16 +00:00
{
2010-12-04 17:45:48 +00:00
/* insert mixer */
2010-10-15 00:20:15 +00:00
InsertHeadList ( & MixerList - > MixerList , & MixerInfo - > Entry ) ;
2010-12-04 17:45:48 +00:00
/* increment mixer count */
MixerList - > MixerListCount + + ;
2009-12-10 12:27:16 +00:00
}
2010-10-15 00:20:15 +00:00
/* done */
2009-12-08 21:10:02 +00:00
return Status ;
}
MIXER_STATUS
MMixerSetupFilter (
2009-12-09 09:51:39 +00:00
IN PMIXER_CONTEXT MixerContext ,
IN PMIXER_LIST MixerList ,
2009-12-18 10:25:41 +00:00
IN LPMIXER_DATA MixerData ,
IN PULONG DeviceCount )
2009-12-08 21:10:02 +00:00
{
MIXER_STATUS Status ;
2010-10-15 00:20:15 +00:00
PTOPOLOGY Topology ;
2009-12-08 21:10:02 +00:00
ULONG NodeIndex ;
2010-12-04 17:45:48 +00:00
LPMIXER_INFO MixerInfo = NULL ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
/* check if topology has already been built */
if ( MixerData - > Topology = = NULL )
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* build topology */
Status = MMixerBuildTopology ( MixerContext , MixerData , & Topology ) ;
2009-12-08 21:10:02 +00:00
2010-10-15 00:20:15 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to build topology */
return Status ;
}
/* store topology */
MixerData - > Topology = Topology ;
}
else
2009-12-08 21:10:02 +00:00
{
2010-10-15 00:20:15 +00:00
/* re-use topology */
Topology = MixerData - > Topology ;
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* check if the filter has an wave out node */
NodeIndex = MMixerGetNodeIndexFromGuid ( Topology , & KSNODETYPE_DAC ) ;
2009-12-08 21:10:02 +00:00
if ( NodeIndex ! = MAXULONG )
{
2010-10-15 00:20:15 +00:00
/* it has */
2010-12-04 17:45:48 +00:00
Status = MMixerInitializeFilter ( MixerContext , MixerList , MixerData , NULL , Topology , NodeIndex , FALSE , & MixerInfo ) ;
2010-10-15 00:20:15 +00:00
/* check for success */
2009-12-08 21:10:02 +00:00
if ( Status = = MM_STATUS_SUCCESS )
{
2010-10-15 00:20:15 +00:00
/* increment mixer count */
2009-12-08 21:10:02 +00:00
( * DeviceCount ) + + ;
}
2010-12-04 17:45:48 +00:00
else
{
/* reset mixer info in case of error */
MixerInfo = NULL ;
}
2009-12-08 21:10:02 +00:00
}
2010-10-15 00:20:15 +00:00
/* check if the filter has an wave in node */
NodeIndex = MMixerGetNodeIndexFromGuid ( Topology , & KSNODETYPE_ADC ) ;
2009-12-08 21:10:02 +00:00
if ( NodeIndex ! = MAXULONG )
{
2010-10-15 00:20:15 +00:00
/* it has */
2010-12-04 17:45:48 +00:00
Status = MMixerInitializeFilter ( MixerContext , MixerList , MixerData , MixerInfo , Topology , NodeIndex , TRUE , & MixerInfo ) ;
2010-10-15 00:20:15 +00:00
/* check for success */
2009-12-08 21:10:02 +00:00
if ( Status = = MM_STATUS_SUCCESS )
{
2010-10-15 00:20:15 +00:00
/* increment mixer count */
2009-12-08 21:10:02 +00:00
( * DeviceCount ) + + ;
}
}
2010-12-04 17:45:48 +00:00
/* TODO: handle alternative mixer types + apply hacks for Wave source line */
2010-10-31 14:34:41 +00:00
/* activate midi devices */
MMixerInitializeMidiForFilter ( MixerContext , MixerList , MixerData , Topology ) ;
2010-10-15 00:20:15 +00:00
/* done */
2009-12-08 21:10:02 +00:00
return Status ;
}
2010-01-02 01:52:12 +00:00
MIXER_STATUS
MMixerAddEvent (
IN PMIXER_CONTEXT MixerContext ,
IN OUT LPMIXER_INFO MixerInfo ,
2010-10-15 02:24:35 +00:00
IN PVOID MixerEventContext ,
IN PMIXER_EVENT MixerEventRoutine )
2010-01-02 01:52:12 +00:00
{
2010-10-15 02:24:35 +00:00
//KSE_NODE Property;
PEVENT_NOTIFICATION_ENTRY EventData ;
//ULONG BytesReturned;
//MIXER_STATUS Status;
2010-01-02 01:52:12 +00:00
2010-10-15 02:24:35 +00:00
EventData = ( PEVENT_NOTIFICATION_ENTRY ) MixerContext - > AllocEventData ( sizeof ( EVENT_NOTIFICATION_ENTRY ) ) ;
2010-01-02 01:52:12 +00:00
if ( ! EventData )
{
2010-10-15 00:20:15 +00:00
/* not enough memory */
2010-01-02 01:52:12 +00:00
return MM_STATUS_NO_MEMORY ;
}
2010-10-15 02:24:35 +00:00
#if 0
2010-01-02 01:52:12 +00:00
/* setup request */
Property . Event . Set = KSEVENTSETID_AudioControlChange ;
Property . Event . Flags = KSEVENT_TYPE_TOPOLOGY | KSEVENT_TYPE_ENABLE ;
Property . Event . Id = KSEVENT_CONTROL_CHANGE ;
Property . NodeId = NodeId ;
Property . Reserved = 0 ;
Status = MixerContext - > Control ( MixerInfo - > hMixer , IOCTL_KS_ENABLE_EVENT , ( PVOID ) & Property , sizeof ( KSP_NODE ) , ( PVOID ) EventData , sizeof ( KSEVENTDATA ) , & BytesReturned ) ;
if ( Status ! = MM_STATUS_SUCCESS )
{
2010-10-15 00:20:15 +00:00
/* failed to add event */
2010-01-02 01:52:12 +00:00
MixerContext - > FreeEventData ( EventData ) ;
return Status ;
}
2010-10-15 02:24:35 +00:00
# endif
/* initialize notification entry */
EventData - > MixerEventContext = MixerEventContext ;
EventData - > MixerEventRoutine ;
2010-01-02 01:52:12 +00:00
2010-10-15 00:20:15 +00:00
/* store event */
2010-01-02 01:52:12 +00:00
InsertTailList ( & MixerInfo - > EventList , & EventData - > Entry ) ;
return MM_STATUS_SUCCESS ;
}
2010-10-15 02:24:35 +00:00