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"
2010-12-05 18:01:24 +00:00
const GUID KSNODETYPE_DESKTOP_MICROPHONE = { 0xDFF21BE2 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_LEGACY_AUDIO_CONNECTOR = { 0xDFF21FE4 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_TELEPHONE = { 0xDFF21EE2 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_PHONE_LINE = { 0xDFF21EE1 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_DOWN_LINE_PHONE = { 0xDFF21EE3 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_DESKTOP_SPEAKER = { 0xDFF21CE4 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_ROOM_SPEAKER = { 0xDFF21CE5 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_COMMUNICATION_SPEAKER = { 0xDFF21CE6 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_HEADPHONES = { 0xDFF21CE2 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO = { 0xDFF21CE3 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_MICROPHONE = { 0xDFF21BE1 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSCATEGORY_AUDIO = { 0x6994AD04L , 0x93EF , 0x11D0 , { 0xA3 , 0xCC , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_SPDIF_INTERFACE = { 0xDFF21FE5 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_ANALOG_CONNECTOR = { 0xDFF21FE1 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_SPEAKER = { 0xDFF21CE1 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_CD_PLAYER = { 0xDFF220E3 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_SYNTHESIZER = { 0xDFF220F3 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID KSNODETYPE_LINE_CONNECTOR = { 0xDFF21FE3 , 0xF70F , 0x11D0 , { 0xB9 , 0x17 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
const GUID PINNAME_VIDEO_CAPTURE = { 0xfb6c4281 , 0x353 , 0x11d1 , { 0x90 , 0x5f , 0x0 , 0x0 , 0xc0 , 0xcc , 0x16 , 0xba } } ;
2009-12-08 21:10:02 +00:00
MIXER_STATUS
MMixerAddMixerControl (
IN PMIXER_CONTEXT MixerContext ,
IN LPMIXER_INFO MixerInfo ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-10-15 00:20:15 +00:00
IN PTOPOLOGY Topology ,
2009-12-08 21:10:02 +00:00
IN ULONG NodeIndex ,
2010-12-07 10:29:57 +00:00
IN LPMIXERLINE_EXT MixerLine )
2009-12-08 21:10:02 +00:00
{
LPGUID NodeType ;
KSP_NODE Node ;
ULONG BytesReturned ;
MIXER_STATUS Status ;
LPWSTR Name ;
2010-12-07 10:29:57 +00:00
LPMIXERCONTROL_EXT MixerControl ;
/* allocate mixer control */
MixerControl = MixerContext - > Alloc ( sizeof ( MIXERCONTROL_EXT ) ) ;
if ( ! MixerControl )
{
/* no memory */
return MM_STATUS_NO_MEMORY ;
}
2009-12-08 21:10:02 +00:00
/* initialize mixer control */
2010-12-07 10:29:57 +00:00
MixerControl - > hDevice = hMixer ;
MixerControl - > NodeID = NodeIndex ;
MixerControl - > ExtraData = NULL ;
MixerControl - > Control . cbStruct = sizeof ( MIXERCONTROLW ) ;
MixerControl - > Control . dwControlID = MixerInfo - > ControlId ;
2009-12-08 21:10:02 +00:00
/* 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 */
2010-12-07 10:29:57 +00:00
MixerControl - > Control . dwControlType = MMixerGetControlTypeFromTopologyNode ( NodeType ) ;
2009-12-08 21:10:02 +00:00
2010-12-07 10:29:57 +00:00
MixerControl - > Control . fdwControl = MIXERCONTROL_CONTROLF_UNIFORM ; /* FIXME */
MixerControl - > Control . cMultipleItems = 0 ;
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-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( 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-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( 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
{
2010-12-07 10:29:57 +00:00
MixerContext - > Copy ( MixerControl - > Control . szShortName , Name , ( min ( MIXER_SHORT_NAME_CHARS , wcslen ( Name ) + 1 ) ) * sizeof ( WCHAR ) ) ;
MixerControl - > Control . szShortName [ MIXER_SHORT_NAME_CHARS - 1 ] = L ' \0 ' ;
2009-12-08 21:10:02 +00:00
2010-12-07 10:29:57 +00:00
MixerContext - > Copy ( MixerControl - > Control . szName , Name , ( min ( MIXER_LONG_NAME_CHARS , wcslen ( Name ) + 1 ) ) * sizeof ( WCHAR ) ) ;
MixerControl - > Control . szName [ MIXER_LONG_NAME_CHARS - 1 ] = L ' \0 ' ;
2009-12-08 21:10:02 +00:00
}
/* free name buffer */
MixerContext - > Free ( Name ) ;
}
2010-12-07 10:29:57 +00:00
/* increment control count */
2009-12-08 21:10:02 +00:00
MixerInfo - > ControlId + + ;
2010-12-06 16:00:06 +00:00
2010-12-07 10:29:57 +00:00
/* insert control */
InsertTailList ( & MixerLine - > ControlsList , & MixerControl - > Entry ) ;
if ( MixerControl - > Control . dwControlType = = MIXERCONTROL_CONTROLTYPE_MUX )
2009-12-08 21:10:02 +00:00
{
2010-12-06 16:00:06 +00:00
ULONG NodesCount ;
PULONG Nodes ;
2009-12-08 21:10:02 +00:00
2010-12-06 16:00:06 +00:00
/* allocate topology nodes array */
Status = MMixerAllocateTopologyNodeArray ( MixerContext , Topology , & Nodes ) ;
2009-12-08 21:10:02 +00:00
2010-12-06 16:00:06 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
/* out of memory */
return STATUS_NO_MEMORY ;
}
2009-12-08 21:10:02 +00:00
2010-12-06 16:00:06 +00:00
/* get connected node count */
MMixerGetNextNodesFromNodeIndex ( MixerContext , Topology , NodeIndex , TRUE , & NodesCount , Nodes ) ;
2009-12-08 21:10:02 +00:00
2010-12-06 16:00:06 +00:00
/* TODO */
MixerContext - > Free ( Nodes ) ;
/* setup mux bounds */
2010-12-07 10:29:57 +00:00
MixerControl - > Control . Bounds . dwMinimum = 0 ;
MixerControl - > Control . Bounds . dwMaximum = NodesCount - 1 ;
MixerControl - > Control . Metrics . dwReserved [ 0 ] = NodesCount ;
MixerControl - > Control . cMultipleItems = NodesCount ;
MixerControl - > Control . fdwControl | = MIXERCONTROL_CONTROLF_MULTIPLE ;
2010-12-06 16:00:06 +00:00
}
2010-12-07 10:29:57 +00:00
else if ( MixerControl - > Control . dwControlType = = MIXERCONTROL_CONTROLTYPE_MUTE )
2010-12-06 16:00:06 +00:00
{
2010-12-07 10:29:57 +00:00
MixerControl - > Control . Bounds . dwMinimum = 0 ;
MixerControl - > Control . Bounds . dwMaximum = 1 ;
2010-12-06 16:00:06 +00:00
}
2010-12-07 10:29:57 +00:00
else if ( MixerControl - > Control . dwControlType = = MIXERCONTROL_CONTROLTYPE_ONOFF )
2010-12-06 16:00:06 +00:00
{
/* only needs to set bounds */
2010-12-07 10:29:57 +00:00
MixerControl - > Control . Bounds . dwMinimum = 0 ;
MixerControl - > Control . Bounds . dwMaximum = 1 ;
2010-12-06 16:00:06 +00:00
}
2010-12-07 10:29:57 +00:00
else if ( MixerControl - > Control . dwControlType = = MIXERCONTROL_CONTROLTYPE_VOLUME )
2009-12-08 21:10:02 +00:00
{
KSNODEPROPERTY_AUDIO_CHANNEL Property ;
ULONG Length ;
PKSPROPERTY_DESCRIPTION Desc ;
PKSPROPERTY_MEMBERSHEADER Members ;
PKSPROPERTY_STEPPING_LONG Range ;
2010-12-07 10:29:57 +00:00
MixerControl - > Control . Bounds . dwMinimum = 0 ;
MixerControl - > Control . Bounds . dwMaximum = 0xFFFF ;
MixerControl - > Control . Metrics . cSteps = 0xC0 ; /* FIXME */
2010-12-06 16:00:06 +00:00
2009-12-08 21:10:02 +00:00
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 ;
2010-12-06 16:00:06 +00:00
Property . NodeProperty . Property . Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY ;
2009-12-08 21:10:02 +00:00
Property . NodeProperty . Property . Set = KSPROPSETID_Audio ;
/* get node volume level info */
2010-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( 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 */
2010-12-07 10:29:57 +00:00
VolumeData - > Header . dwControlID = MixerControl - > Control . dwControlID ;
2009-12-08 21:10:02 +00:00
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 ;
}
2010-12-07 10:29:57 +00:00
MixerControl - > ExtraData = VolumeData ;
2009-12-08 21:10:02 +00:00
}
}
MixerContext - > Free ( Desc ) ;
}
2010-12-07 10:29:57 +00:00
DPRINT ( " Status %x Name %S \n " , Status , MixerControl - > Control . szName ) ;
2009-12-08 21:10:02 +00:00
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 ) ;
2010-12-07 15:19:22 +00:00
DestinationLine - > Line . cChannels = 2 ; /* FIXME */
DestinationLine - > Line . cConnections = 0 ;
DestinationLine - > Line . cControls = 0 ;
DestinationLine - > Line . dwComponentType = ( bInputMixer = = 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN ) ;
DestinationLine - > Line . dwDestination = MixerInfo - > MixCaps . cDestinations ;
2010-12-04 17:45:48 +00:00
DestinationLine - > Line . dwLineID = MixerInfo - > MixCaps . cDestinations + DESTINATION_LINE ;
2010-12-07 15:19:22 +00:00
DestinationLine - > Line . dwSource = MAXULONG ;
2010-10-15 00:20:15 +00:00
DestinationLine - > Line . dwUser = 0 ;
2010-12-07 15:19:22 +00:00
DestinationLine - > Line . fdwLine = MIXERLINE_LINEF_ACTIVE ;
2010-10-15 00:20:15 +00:00
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 */
2010-12-07 10:29:57 +00:00
InitializeListHead ( & DestinationLine - > ControlsList ) ;
2010-10-15 00:20:15 +00:00
/* 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 ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
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 */
2010-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( 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 */
2010-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Pin , sizeof ( KSP_PIN ) , ( PVOID ) Buffer , BytesReturned , & BytesReturned ) ;
2010-10-15 00:20:15 +00:00
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 ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-10-15 00:20:15 +00:00
IN ULONG PinId ,
IN ULONG bInput )
{
LPWSTR PinName ;
MIXER_STATUS Status ;
/* try get pin name */
2010-12-07 10:29:57 +00:00
Status = MMixerGetPinName ( MixerContext , MixerInfo , hMixer , PinId , & PinName ) ;
2010-10-15 00:20:15 +00:00
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 ;
}
2010-12-06 02:15:33 +00:00
MIXER_STATUS
MMixerGetChannelCountEnhanced (
IN PMIXER_CONTEXT MixerContext ,
IN LPMIXER_INFO MixerInfo ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-12-06 02:15:33 +00:00
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 */
2010-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Request , sizeof ( KSP_NODE ) , ( PVOID ) & Description , sizeof ( KSPROPERTY_DESCRIPTION ) , & BytesReturned ) ;
2010-12-06 02:15:33 +00:00
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 */
2010-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Request , sizeof ( KSP_NODE ) , ( PVOID ) NewDescription , Description . DescriptionSize , & BytesReturned ) ;
2010-12-06 02:15:33 +00:00
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 ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-12-06 02:15:33 +00:00
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 */
2010-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Channel , sizeof ( KSNODEPROPERTY_AUDIO_CHANNEL ) , ( PVOID ) & Volume , sizeof ( LONG ) , & BytesReturned ) ;
2010-12-06 02:15:33 +00:00
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 ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-12-06 02:15:33 +00:00
IN ULONG NodeId ,
OUT PULONG MaxChannels )
{
MIXER_STATUS Status ;
/* try to get it enhanced */
2010-12-07 10:29:57 +00:00
Status = MMixerGetChannelCountEnhanced ( MixerContext , MixerInfo , hMixer , NodeId , MaxChannels ) ;
2010-12-06 02:15:33 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
/* get it old-fashioned way */
2010-12-07 10:29:57 +00:00
MMixerGetChannelCountLegacy ( MixerContext , MixerInfo , hMixer , NodeId , MaxChannels ) ;
2010-12-06 02:15:33 +00:00
}
}
2010-10-15 00:20:15 +00:00
MIXER_STATUS
MMixerAddMixerControlsToMixerLineByNodeIndexArray (
IN PMIXER_CONTEXT MixerContext ,
IN LPMIXER_INFO MixerInfo ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-10-15 00:20:15 +00:00
IN PTOPOLOGY Topology ,
IN OUT LPMIXERLINE_EXT DstLine ,
IN ULONG NodesCount ,
IN PULONG Nodes )
{
ULONG Index , Count , bReserved ;
MIXER_STATUS Status ;
2010-12-06 02:15:33 +00:00
LPGUID NodeType ;
ULONG MaxChannels ;
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-12-06 02:15:33 +00:00
/* query node type */
NodeType = MMixerGetNodeTypeFromTopology ( Topology , Nodes [ Index ] ) ;
if ( IsEqualGUIDAligned ( NodeType , & KSNODETYPE_VOLUME ) )
{
/* calculate maximum channel count for node */
2010-12-07 10:29:57 +00:00
MMixerGetMaxChannelsForNode ( MixerContext , MixerInfo , hMixer , Nodes [ Index ] , & MaxChannels ) ;
2010-12-06 02:15:33 +00:00
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 ) ;
}
2010-10-15 00:20:15 +00:00
/* now add the mixer control */
2010-12-07 10:29:57 +00:00
Status = MMixerAddMixerControl ( MixerContext , MixerInfo , hMixer , Topology , Nodes [ Index ] , DstLine ) ;
2010-10-15 00:20:15 +00:00
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 ;
}
2010-12-05 18:01:24 +00:00
MIXER_STATUS
MMixerGetComponentAndTargetType (
IN PMIXER_CONTEXT MixerContext ,
IN OUT LPMIXER_INFO MixerInfo ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-12-05 18:01:24 +00:00
IN ULONG PinId ,
OUT PULONG ComponentType ,
OUT PULONG TargetType )
{
KSPIN_DATAFLOW DataFlow ;
KSPIN_COMMUNICATION Communication ;
MIXER_STATUS Status ;
KSP_PIN Request ;
ULONG BytesReturned ;
GUID Guid ;
BOOLEAN BridgePin = FALSE ;
PKSPIN_PHYSICALCONNECTION Connection ;
/* first dataflow type */
2010-12-07 10:29:57 +00:00
Status = MMixerGetPinDataFlowAndCommunication ( MixerContext , hMixer , PinId , & DataFlow , & Communication ) ;
2010-12-05 18:01:24 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to get dataflow */
return Status ;
}
/* now get pin category guid */
Request . PinId = PinId ;
Request . Reserved = 0 ;
Request . Property . Flags = KSPROPERTY_TYPE_GET ;
Request . Property . Set = KSPROPSETID_Pin ;
Request . Property . Id = KSPROPERTY_PIN_CATEGORY ;
/* get pin category */
2010-12-07 10:29:57 +00:00
Status = MixerContext - > Control ( hMixer , IOCTL_KS_PROPERTY , ( PVOID ) & Request , sizeof ( KSP_PIN ) , & Guid , sizeof ( GUID ) , & BytesReturned ) ;
2010-12-05 18:01:24 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to get dataflow */
return Status ;
}
/* check if it has a physical connection */
2010-12-07 10:29:57 +00:00
Status = MMixerGetPhysicalConnection ( MixerContext , hMixer , PinId , & Connection ) ;
2010-12-05 18:01:24 +00:00
if ( Status = = MM_STATUS_SUCCESS )
{
/* pin is a brige pin */
BridgePin = TRUE ;
/* free physical connection */
MixerContext - > Free ( Connection ) ;
}
if ( DataFlow = = KSPIN_DATAFLOW_IN )
{
if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_MICROPHONE ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_DESKTOP_MICROPHONE ) )
{
/* type microphone */
* TargetType = MIXERLINE_TARGETTYPE_WAVEIN ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_LEGACY_AUDIO_CONNECTOR ) | |
IsEqualGUIDAligned ( & Guid , & KSCATEGORY_AUDIO ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_SPEAKER ) )
{
/* type waveout */
* TargetType = MIXERLINE_TARGETTYPE_WAVEOUT ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_CD_PLAYER ) )
{
/* type cd player */
* TargetType = MIXERLINE_TARGETTYPE_UNDEFINED ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_SYNTHESIZER ) )
{
/* type synthesizer */
* TargetType = MIXERLINE_TARGETTYPE_MIDIOUT ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_LINE_CONNECTOR ) )
{
/* type line */
* TargetType = MIXERLINE_TARGETTYPE_UNDEFINED ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_TELEPHONE ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_PHONE_LINE ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_DOWN_LINE_PHONE ) )
{
/* type telephone */
* TargetType = MIXERLINE_TARGETTYPE_UNDEFINED ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_ANALOG_CONNECTOR ) )
{
/* type analog */
if ( BridgePin )
* TargetType = MIXERLINE_TARGETTYPE_WAVEIN ;
else
* TargetType = MIXERLINE_TARGETTYPE_WAVEOUT ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_ANALOG ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_SPDIF_INTERFACE ) )
{
/* type analog */
if ( BridgePin )
* TargetType = MIXERLINE_TARGETTYPE_WAVEIN ;
else
* TargetType = MIXERLINE_TARGETTYPE_WAVEOUT ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL ;
}
else
{
/* unknown type */
* TargetType = MIXERLINE_TARGETTYPE_UNDEFINED ;
* ComponentType = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED ;
DPRINT1 ( " Unknown Category for PinId %lu BridgePin %lu \n " , PinId , BridgePin ) ;
}
}
else
{
if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_SPEAKER ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_DESKTOP_SPEAKER ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_ROOM_SPEAKER ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_COMMUNICATION_SPEAKER ) )
{
/* type waveout */
* TargetType = MIXERLINE_TARGETTYPE_WAVEOUT ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSCATEGORY_AUDIO ) | |
IsEqualGUIDAligned ( & Guid , & PINNAME_CAPTURE ) )
{
/* type wavein */
* TargetType = MIXERLINE_TARGETTYPE_WAVEIN ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_HEADPHONES ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO ) )
{
/* type head phones */
* TargetType = MIXERLINE_TARGETTYPE_WAVEOUT ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_TELEPHONE ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_PHONE_LINE ) | |
IsEqualGUIDAligned ( & Guid , & KSNODETYPE_DOWN_LINE_PHONE ) )
{
/* type waveout */
* TargetType = MIXERLINE_TARGETTYPE_UNDEFINED ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_TELEPHONE ;
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_ANALOG_CONNECTOR ) )
{
/* type analog */
if ( BridgePin )
{
* TargetType = MIXERLINE_TARGETTYPE_WAVEOUT ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS ;
}
else
{
* TargetType = MIXERLINE_TARGETTYPE_WAVEIN ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN ;
}
}
else if ( IsEqualGUIDAligned ( & Guid , & KSNODETYPE_SPDIF_INTERFACE ) )
{
/* type spdif */
if ( BridgePin )
{
* TargetType = MIXERLINE_TARGETTYPE_WAVEOUT ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS ;
}
else
{
* TargetType = MIXERLINE_TARGETTYPE_WAVEIN ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN ;
}
}
else
{
/* unknown type */
* TargetType = MIXERLINE_TARGETTYPE_UNDEFINED ;
* ComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED ;
DPRINT1 ( " Unknown Category for PinId %lu BridgePin %lu \n " , PinId , BridgePin ) ;
}
}
/* done */
return MM_STATUS_SUCCESS ;
}
2009-12-08 21:10:02 +00:00
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 ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-10-15 00:20:15 +00:00
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 ;
2010-12-05 18:01:24 +00:00
ULONG ComponentType , TargetType ;
/* get component and target type */
2010-12-07 10:29:57 +00:00
Status = MMixerGetComponentAndTargetType ( MixerContext , MixerInfo , hMixer , PinId , & ComponentType , & TargetType ) ;
2010-12-05 18:01:24 +00:00
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to get component status */
TargetType = MIXERLINE_TARGETTYPE_UNDEFINED ;
ComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED ;
}
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 - > PinId = PinId ;
/* initialize mixer line */
SrcLine - > Line . cbStruct = sizeof ( MIXERLINEW ) ;
2010-12-05 18:01:24 +00:00
SrcLine - > Line . dwDestination = MixerInfo - > MixCaps . cDestinations - 1 ;
2010-10-15 00:20:15 +00:00
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 ;
2010-12-05 18:01:24 +00:00
SrcLine - > Line . dwComponentType = ComponentType ;
2010-10-15 00:20:15 +00:00
SrcLine - > Line . dwUser = 0 ;
SrcLine - > Line . cChannels = DstLine - > Line . cChannels ;
SrcLine - > Line . cConnections = 0 ;
2010-12-05 18:01:24 +00:00
SrcLine - > Line . Target . dwType = TargetType ;
2010-10-15 00:20:15 +00:00
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 ;
2010-12-07 10:29:57 +00:00
InitializeListHead ( & SrcLine - > ControlsList ) ;
2010-10-15 00:20:15 +00:00
/* copy name */
ASSERT ( MixerInfo - > MixCaps . szPname [ MAXPNAMELEN - 1 ] = = L ' \0 ' ) ;
wcscpy ( SrcLine - > Line . Target . szPname , MixerInfo - > MixCaps . szPname ) ;
/* get pin name */
2010-12-07 10:29:57 +00:00
Status = MMixerGetPinName ( MixerContext , MixerInfo , hMixer , PinId , & PinName ) ;
2010-10-15 00:20:15 +00:00
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 */
2010-12-07 10:29:57 +00:00
Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray ( MixerContext , MixerInfo , hMixer , Topology , SrcLine , NodesCount , Nodes ) ;
2010-10-15 00:20:15 +00:00
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 ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-10-15 00:20:15 +00:00
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-07 10:29:57 +00:00
Status = MMixerBuildMixerSourceLine ( MixerContext , MixerInfo , hMixer , 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-07 10:29:57 +00:00
/* mark pin as reserved */
MMixerSetTopologyPinReserved ( Topology , PinId ) ;
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-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
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 */
2010-12-07 10:29:57 +00:00
Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray ( MixerContext , MixerInfo , hMixer , Topology , DstLine , NodesCount , Nodes ) ;
2010-10-15 00:20:15 +00:00
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 ,
2010-12-07 10:29:57 +00:00
IN HANDLE hMixer ,
2010-10-17 21:15:21 +00:00
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 */
2010-12-07 10:29:57 +00:00
Status = MMixerGetPhysicalConnection ( MixerContext , hMixer , Pins [ Index ] , & Connection ) ;
2010-10-17 21:15:21 +00:00
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 ) ;
2010-12-07 15:19:22 +00:00
/* sanity check */
ASSERT ( MixerData - > MixerInfo = = NULL | | MixerData - > MixerInfo = = MixerInfo ) ;
/* associate with mixer */
MixerData - > MixerInfo = MixerInfo ;
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-12-07 10:29:57 +00:00
/* mark pin as consumed */
MMixerSetTopologyPinReserved ( Topology , OutConnection - > Pin ) ;
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-12-07 10:29:57 +00:00
/* allocate pin index array which will hold all referenced pins */
Status = MMixerAllocateTopologyPinArray ( MixerContext , Topology , & Pins ) ;
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to create topology */
return Status ;
}
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
*/
2010-12-07 10:29:57 +00:00
MMixerApplyOutputFilterHack ( MixerContext , MixerData , MixerData - > hDevice , & 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 */
2010-12-07 10:29:57 +00:00
Status = MMixerBuildMixerDestinationLine ( MixerContext , MixerInfo , MixerData - > hDevice , 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-07 10:29:57 +00:00
Status = MMixerAddMixerControlsToDestinationLine ( MixerContext , MixerInfo , MixerData - > hDevice , 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-07 10:29:57 +00:00
Status = MMixerAddMixerSourceLines ( MixerContext , MixerInfo , MixerData - > hDevice , Topology , DestinationLineID , LineTerminator ) ;
2010-10-15 00:20:15 +00:00
}
2010-12-07 10:29:57 +00:00
/* mark pin as consumed */
MMixerSetTopologyPinReserved ( Topology , Pins [ 0 ] ) ;
/* free topology pin array */
MixerContext - > Free ( Pins ) ;
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 */
2010-12-07 10:29:57 +00:00
Status = MMixerAddMixerControlsToDestinationLine ( MixerContext , MixerInfo , MixerData - > hDevice , 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-07 10:29:57 +00:00
Status = MMixerAddMixerSourceLines ( MixerContext , MixerInfo , MixerData - > hDevice , 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-07 10:29:57 +00:00
ULONG Index ;
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 ) ;
2010-12-07 15:19:22 +00:00
/* associate with mixer data */
MixerData - > MixerInfo = MixerInfo ;
2010-12-04 17:45:48 +00:00
}
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-12-07 10:29:57 +00:00
/* mark all found pins as reserved */
for ( Index = 0 ; Index < PinsFound ; Index + + )
{
MMixerSetTopologyPinReserved ( Topology , Pins [ Index ] ) ;
}
2010-10-15 00:20:15 +00:00
if ( bInputMixer )
{
/* pre create the mixer destination line for input mixers */
2010-12-07 10:29:57 +00:00
Status = MMixerBuildMixerDestinationLine ( MixerContext , MixerInfo , MixerData - > hDevice , 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 )
{
2010-12-07 10:29:57 +00:00
/* mark pin as reserved */
MMixerSetTopologyPinReserved ( Topology , Pins [ 0 ] ) ;
2010-10-15 00:20:15 +00:00
/* 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 ) ;
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 ;
}
2010-12-07 10:29:57 +00:00
VOID
MMixerHandleAlternativeMixers (
IN PMIXER_CONTEXT MixerContext ,
IN PMIXER_LIST MixerList ,
IN LPMIXER_DATA MixerData ,
IN PTOPOLOGY Topology )
{
ULONG Index , PinCount , Reserved ;
2010-12-07 15:19:22 +00:00
MIXER_STATUS Status ;
ULONG DestinationLineID , LineTerminator ;
LPMIXERLINE_EXT DstLine ;
2010-12-07 10:29:57 +00:00
DPRINT1 ( " DeviceName %S \n " , MixerData - > DeviceName ) ;
/* get topology pin count */
MMixerGetTopologyPinCount ( Topology , & PinCount ) ;
for ( Index = 0 ; Index < PinCount ; Index + + )
{
MMixerIsTopologyPinReserved ( Topology , Index , & Reserved ) ;
/* check if it has already been reserved */
2010-12-07 15:19:22 +00:00
if ( Reserved = = TRUE )
{
/* pin has already been reserved */
continue ;
}
DPRINT ( " MixerName %S Available PinID %lu \n " , MixerData - > DeviceName , Index ) ;
/* sanity check */
ASSERT ( MixerData - > MixerInfo ) ;
if ( ! MixerData - > MixerInfo )
2010-12-07 10:29:57 +00:00
{
2010-12-07 15:19:22 +00:00
DPRINT1 ( " Expected mixer info \n " ) ;
continue ;
2010-12-07 10:29:57 +00:00
}
2010-12-07 15:19:22 +00:00
/* build the destination line */
Status = MMixerBuildMixerDestinationLine ( MixerContext , MixerData - > MixerInfo , MixerData - > hDevice , Index , TRUE ) ;
if ( Status ! = MM_STATUS_SUCCESS )
{
/* failed to build destination line */
continue ;
}
/* calculate destination line id */
DestinationLineID = ( DESTINATION_LINE + MixerData - > MixerInfo - > MixCaps . cDestinations - 1 ) ;
/* add mixer controls to destination line */
Status = MMixerAddMixerControlsToDestinationLine ( MixerContext , MixerData - > MixerInfo , MixerData - > hDevice , MixerData - > Topology , Index , TRUE , DestinationLineID , & LineTerminator ) ;
if ( Status = = MM_STATUS_SUCCESS )
{
/* now add the rest of the source lines */
Status = MMixerAddMixerSourceLines ( MixerContext , MixerData - > MixerInfo , MixerData - > hDevice , MixerData - > Topology , DestinationLineID , LineTerminator ) ;
}
/* mark pin as consumed */
MMixerSetTopologyPinReserved ( Topology , Index ) ;
/* now grab destination line */
DstLine = MMixerGetSourceMixerLineByLineId ( MixerData - > MixerInfo , DestinationLineID ) ;
/* set type and target as undefined */
DstLine - > Line . dwComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED ;
DstLine - > Line . Target . dwType = MIXERLINE_TARGETTYPE_UNDEFINED ;
DstLine - > Line . Target . vDriverVersion = 0 ;
DstLine - > Line . Target . wMid = 0 ;
DstLine - > Line . Target . wPid = 0 ;
2010-12-07 10:29:57 +00:00
}
}
2009-12-08 21:10:02 +00:00
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-07 10:29:57 +00:00
/* TODO: apply hacks for Wave source line */
2010-12-04 17:45:48 +00:00
2010-10-31 14:34:41 +00:00
/* activate midi devices */
2010-12-07 15:19:22 +00:00
//MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology);
2010-10-31 14:34:41 +00:00
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