|
|
//---------------------------------------------------------------------------
//
// Module: mixer.h
//
// Description:
//
// Contains the declarations and prototypes for the Kernel Portion
// of the mixer line driver (KMXL).
//
//
//@@BEGIN_MSINTERNAL
// Development Team:
// D. Baumberger
//
// History: Date Author Comment
//
//@@END_MSINTERNAL
//
//---------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (C) Microsoft Corporation, 1997 - 1999 All Rights Reserved.
//
//---------------------------------------------------------------------------
#ifndef _MIXER_H_INCLUDED_
#define _MIXER_H_INCLUDED_
//#define API_TRACE
//#define PARSE_TRACE
#define SUPERMIX_AS_VOL
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// M I X E R L I N E 1 6 - b i t S T R U C T U R E S //
// ( A N S I ) //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
#ifdef WIN32
# include <pshpack1.h>
#else
# ifndef RC_INVOKED
# pragma pack(1)
# endif
#endif
typedef struct tagMIXERLINE16 { DWORD cbStruct; /* size of MIXERLINE structure */ DWORD dwDestination; /* zero based destination index */ DWORD dwSource; /* zero based source index (if source) */ DWORD dwLineID; /* unique line id for mixer device */ DWORD fdwLine; /* state/information about line */ DWORD dwUser; /* driver specific information */ DWORD dwComponentType; /* component type line connects to */ DWORD cChannels; /* number of channels line supports */ DWORD cConnections; /* number of connections [possible] */ DWORD cControls; /* number of controls at this line */ CHAR szShortName[MIXER_SHORT_NAME_CHARS]; CHAR szName[MIXER_LONG_NAME_CHARS]; struct { DWORD dwType; /* MIXERLINE_TARGETTYPE_xxxx */ DWORD dwDeviceID; /* target device ID of device type */ WORD wMid; /* of target device */ WORD wPid; /* " */ WORD vDriverVersion; /* " */ CHAR szPname[MAXPNAMELEN]; /* " */ } Target; } MIXERLINE16, *PMIXERLINE16, *LPMIXERLINE16;
typedef struct tagMIXERCONTROL16 { DWORD cbStruct; /* size in bytes of MIXERCONTROL */ DWORD dwControlID; /* unique control id for mixer device */ DWORD dwControlType; /* MIXERCONTROL_CONTROLTYPE_xxx */ DWORD fdwControl; /* MIXERCONTROL_CONTROLF_xxx */ DWORD cMultipleItems; /* if MIXERCONTROL_CONTROLF_MULTIPLE set */ CHAR szShortName[MIXER_SHORT_NAME_CHARS]; CHAR szName[MIXER_LONG_NAME_CHARS]; union { struct { LONG lMinimum; /* signed minimum for this control */ LONG lMaximum; /* signed maximum for this control */ }; struct { DWORD dwMinimum; /* unsigned minimum for this control */ DWORD dwMaximum; /* unsigned maximum for this control */ }; DWORD dwReserved[6]; } Bounds; union { DWORD cSteps; /* # of steps between min & max */ DWORD cbCustomData; /* size in bytes of custom data */ DWORD dwReserved[6]; /* !!! needed? we have cbStruct.... */ } Metrics; } MIXERCONTROL16, *PMIXERCONTROL16, *LPMIXERCONTROL16;
typedef struct tagMIXERLINECONTROLS16 { DWORD cbStruct; /* size in bytes of MIXERLINECONTROLS */ DWORD dwLineID; /* line id (from MIXERLINE.dwLineID) */ union { DWORD dwControlID; /* MIXER_GETLINECONTROLSF_ONEBYID */ DWORD dwControlType; /* MIXER_GETLINECONTROLSF_ONEBYTYPE */ }; DWORD cControls; /* count of controls pmxctrl points to */ DWORD cbmxctrl; /* size in bytes of _one_ MIXERCONTROL */ LPMIXERCONTROL16 pamxctrl; /* pointer to first MIXERCONTROL array */ } MIXERLINECONTROLS16, *PMIXERLINECONTROLS16, *LPMIXERLINECONTROLS16;
typedef struct tagMIXERCONTROLDETAILS_LISTTEXT16 { DWORD dwParam1; DWORD dwParam2; CHAR szName[MIXER_LONG_NAME_CHARS]; } MIXERCONTROLDETAILS_LISTTEXT16, *PMIXERCONTROLDETAILS_LISTTEXT16, *LPMIXERCONTROLDETAILS_LISTTEXT16;
#ifdef WIN32
# include <poppack.h>
#else
# ifndef RC_INVOKED
# pragma pack()
# endif
#endif
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// D E F I N E S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
#define PINID_WILDCARD ( (ULONG) -2 )
#define DESTINATION_LIST ( 0x01 )
#define SOURCE_LIST ( 0x02 )
#define SLIST SINGLE_LIST_ENTRY
#define PSLIST SLIST*
#define MAX_CHANNELS 0xFFFF
//#define MIXERCONTROL_CONTROLTYPE_BASS_BOOST 0x20012277
#define INVALID_ID ( 0xDEADBEEF )
#define TOPOLOGY_DRIVER_NAME L"\\DosDevices\\sysaudio\\MIXER"
//#define TOPOLOGY_DRIVER_NAME L"\\DosDevices\\PortClass0\\TOPOLOGY"
#define STR_SHORT_AGC "AGC"
#define STR_AGC "Automatic Gain Control"
#define STR_SHORT_LOUDNESS "Loudness"
#define STR_LOUDNESS STR_SHORT_LOUDNESS
#define STR_SHORT_MUTE "Mute"
#define STR_MUTE STR_SHORT_MUTE
#define STR_SHORT_TREBLE "Treble"
#define STR_TREBLE STR_SHORT_TREBLE
#define STR_SHORT_BASS "Bass"
#define STR_BASS STR_SHORT_BASS
#define STR_SHORT_VOLUME "Volume"
#define STR_VOLUME STR_SHORT_VOLUME
#define STR_SHORT_MUX "Mux"
#define STR_MUX "Source Mux"
#define STR_SHORT_BASS_BOOST "Bass Boost"
#define STR_BASS_BOOST STR_SHORT_BASS_BOOST
//
// The SwapEm macro function will swap the contents of any SLIST based
// list. A and B are the elements to swap. T is a temporary variable
// of the same type as A and B to use a temporary storage. size is
// the size of the structure in the list, including the SLIST element.
// The macro does not copy the pointer stored in SLIST.
//
#define SwapEm(A, B, T, size) \
memcpy( ((BYTE*) (T)) + sizeof( SLIST ), \ ((BYTE*) (A)) + sizeof( SLIST ), \ size - sizeof( SLIST ) ); \ memcpy( ((BYTE*) (A)) + sizeof( SLIST ), \ ((BYTE*) (B)) + sizeof( SLIST ), \ size - sizeof( SLIST ) ); \ memcpy( ((BYTE*) (B)) + sizeof( SLIST ), \ ((BYTE*) (T)) + sizeof( SLIST ), \ size - sizeof( SLIST ) )
//
// IsValidLine determines if the line pointed to by pLine is valid. A valid
// line is determined by having valid Source and Dest Ids.
//
#define Is_Valid_Line( pLine ) ( ( pLine->SourceId != INVALID_ID ) && \
( pLine->DestId != INVALID_ID ) )
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// F O R W A R D R E F E R E N C E S
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
typedef struct tag_MIXERDEVICE *PMIXERDEVICE;
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// S T R U C T U R E S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
typedef struct tag_CHANNEL_STEPPING { LONG MinValue; LONG MaxValue; LONG Steps; } CHANNEL_STEPPING, *PCHANNEL_STEPPING;
typedef enum tagMXLNODE_TYPE { SOURCE, DESTINATION, NODE } MXLNODE_TYPE;
typedef struct tagMXLCONTROL { SLIST List; // MUST BE THE FIRST MEMBER!
MIXERCONTROL Control; // The MixerControl structure for the control
CONST GUID* NodeType; // The type of node this control represents
ULONG Id; // The Node Id this control represents
ULONG PropertyId; // The KS property used for GET/SET
BOOL bScaled; // Linear->Log scaling
ULONG NumChannels; PCHANNEL_STEPPING pChannelStepping;
union {
//
// Supermixer parameters
//
struct { PLONG pReferenceCount; ULONG Size; PKSAUDIO_MIXCAP_TABLE pMixCaps; PKSAUDIO_MIXLEVEL pMixLevels; // Stored mix levels
};
//
// Parameters for muxes
//
struct { BOOL bPlaceholder; BOOL bHasCopy; // bHasCopy must be
// set to TRUE unless
// this control owns
// the original mem.
ULONG Count; LPMIXERCONTROLDETAILS_LISTTEXT lpmcd_lt; ULONG* pPins; };
} Parameters; #ifdef DEBUG
DWORD Tag; // 'CTRL' if valid control
#endif
} MXLCONTROL, *PMXLCONTROL, *CONTROLLIST;
typedef struct tagMXLLINE { SLIST List; // MUST BE THE FIRST MEMBER!
MIXERLINE Line; // The MixerLine structure for the line
CONTROLLIST Controls; // The list of controls associated with line
ULONG SourceId; // Source Pin Id this line corresponds to
ULONG DestId; // Dest Pin Id this line corresponds to
GUID Type; // The type of line this is
KSPIN_COMMUNICATION Communication; // KSPIN_COMMUNICATION of the line
BOOL bMute; } MXLLINE, *PMXLLINE, *LINELIST;
typedef struct tagPEERNODE* PEERLIST;
typedef struct tagMXLNODE { SLIST List; // MUST BE THE FIRST MEMBER!
MXLNODE_TYPE Type; // Type of node: SOURCE, DEST, or NODE
GUID NodeType; // KSNODETYPE of the node
KSPIN_COMMUNICATION Communication; // KSPIN_COMMUNICATION of the node
ULONG Id; // Pin or node ID
PEERLIST Children; // List of Children
PEERLIST Parents; // List of Parents
} MXLNODE, *PMXLNODE, *NODELIST;
typedef struct tagPEERNODE { SLIST List; // MUST BE THE FIRST MEMBER!
PMXLNODE pNode; // Pointer to the mixer node
} PEERNODE, *PPEERNODE;
typedef struct tagMIXEROBJECT { PFILE_OBJECT pfo; PMXLNODE pNodeTable; PKSTOPOLOGY pTopology; CONTROLLIST listMuxControls; DWORD dwControlId; PMIXERDEVICE pMixerDevice; #ifdef DEBUG
DWORD dwSig; #endif
PWSTR DeviceInterface; } MIXEROBJECT, *PMIXEROBJECT;
typedef enum { MIXER_MAPPING_LOGRITHMIC, MIXER_MAPPING_LINEAR, MIXER_MAPPING_EXPONENTIAL } MIXERMAPPING;
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// M A C R O C I T Y : //
// L I S T M A N A G E M E N T M A C R O F U N C T I O N S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// Next in list retrieval macros
//
#define NextInList( pList, Type ) (( Type* ) ( pList->List.Next ) )
#define kmxlNextNode( pNode ) NextInList( pNode, MXLNODE )
#define kmxlNextPeerNode( pNode ) NextInList( pNode, PEERNODE )
#define kmxlNextControl( pControl ) NextInList( pControl, MXLCONTROL )
#define kmxlNextLine( pLine ) NextInList( pLine, MXLLINE )
//
// First in list retrieval macros
//
#define kmxlFirstInList( NodeList ) ( NodeList )
#define kmxlFirstChildNode( pNode ) (( PEERNODE* ) (pNode)->Children )
#define kmxlFirstParentNode( pNode ) (( PEERNODE* ) (pNode)->Parents )
//
// List count macros
//
#define kmxlParentListLength( pNode ) kmxlListCount( (PSLIST) pNode->Parents )
#define kmxlChildListLength( pNode ) kmxlListCount( (PSLIST) pNode->Children )
#define kmxlListLength( List ) kmxlListCount( (PSLIST) List )
//
// Added to a list macros
//
#define kmxlAddToList( pNodeList, pNode ) \
if( pNodeList ) { \ (pNode)->List.Next = (PSLIST) (pNodeList); \ (pNodeList) = (pNode); \ } else { \ (pNode)->List.Next = NULL; \ (pNodeList) = (pNode); \ }
#define kmxlAddToEndOfList( list, node ) \
kmxlAddElemToEndOfList( ((PSLIST*) &(list)), (PSLIST) (node) )
#define kxmlAddLineToEndOfList( list, node )
#define kmxlAddToChildList( NodeList, Node ) \
ASSERT( (Node)->pNode ); \ kmxlAddToList( (NodeList)->Children, (Node) );
#define kmxlAddToParentList( NodeList, Node ) \
ASSERT( (Node)->pNode ); \ kmxlAddToList( (NodeList)->Parents, (Node) );
//
// Remove from a list macros
//
#define RemoveFirstEntry( list, Type ) \
(Type*) (list); \ { \ PSLIST pRFETemp; \ pRFETemp = (PSLIST) (list); \ if( (list) ) { \ (list) = (Type*) (list)->List.Next; \ if( pRFETemp ) { \ ((Type*) pRFETemp)->List.Next = NULL; \ } \ } \ }
#define kmxlRemoveFirstNode( pNodeList ) \
RemoveFirstEntry( (pNodeList), MXLNODE )
#define kmxlRemoveFirstControl( pControlList ) \
RemoveFirstEntry( (pControlList), MXLCONTROL )
#define kmxlRemoveFirstLine( pLineList ) \
RemoveFirstEntry( (pLineList), MXLLINE )
#define kmxlRemoveFirstPeerNode( pPeerList ) \
RemoveFirstEntry( (pPeerList), PEERNODE )
#define kmxlRemoveFirstChildNode( pNode ) \
RemoveFirstEntry( (pNode)->Children, PEERNODE )
#define kmxlRemoveFirstParentNode( pNode ) \
RemoveFirstEntry( (pNode)->Parents, PEERNODE )
#ifdef DEBUG
#define CONTROL_TAG 'LRTC' //CTRL as seen in memory.
#else
#define CONTROL_TAG
#endif // DEBUG
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// P R O T O T Y P E S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// I N I T I A L I Z A T I O N / D E I N I T I A L I Z A T I O N //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// kmxlInit
//
// Retrieves and parses the topology for a given mixer device number.
// The pfo is an open file object to an instance of a filter that
// will provide the topology.
//
//
NTSTATUS kmxlInit( IN PFILE_OBJECT pfo, // Handle of the topology driver instance
IN PMIXERDEVICE pMixerDevice // The device to initialize for
);
///////////////////////////////////////////////////////////////////////
//
// kmxlDeInit
//
// Cleans up all memory for all devices.
//
//
NTSTATUS kmxlDeInit( IN PMIXERDEVICE pMixerDevice );
///////////////////////////////////////////////////////////////////////
//
// BuildMixerLines
//
// Build the list of mixer lines and stores them into plistLines.
// pcDestinations contains the count of total destinations for the
// given topology, pTopology.
//
//
NTSTATUS kmxlBuildLines( IN PMIXERDEVICE pMixer, // The mixer device
IN PFILE_OBJECT pfoInstance, // The FILE_OBJECT of a filter instance
IN OUT LINELIST* plistLines, // Pointer to the list of all lines
IN OUT PULONG pcDestinations, // Pointer to the number of dests
IN OUT PKSTOPOLOGY pTopology // Pointer to a topology structure
);
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// T O P O L O G Y F U N C T I O N S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// QueryTopology
//
// Queries the topology property on the given instance and stores
// it into pTopology. Note that memory is allocated to store the
// topology.
//
//
NTSTATUS kmxlQueryTopology( IN PFILE_OBJECT pfoInstance, // The instance to query
OUT PKSTOPOLOGY pTopology // The topology structure to fill in
);
///////////////////////////////////////////////////////////////////////
//
// ParseTopology
//
// Parses the topology in pTopology and builds a graph of sources and
// destinations. ppSources will contain a list of all sources nodes
// and ppDests will contain a list of dests. The elements in pNodeTable
// will be updated.
//
//
NTSTATUS kmxlParseTopology( IN PMIXEROBJECT pmxobj, OUT NODELIST* ppSources, // Pointer to the sources list to build
OUT NODELIST* ppDests // Pointer to the dests list to build
);
///////////////////////////////////////////////////////////////////////
//
// BuildChildGraph
//
// For a given node, BuildChildGraph() will build the graph of each
// of the node's children. pNodeTable is updated.
//
//
NTSTATUS kmxlBuildChildGraph( IN PMIXEROBJECT pmxobj, IN NODELIST listDests, // The list of destinations
IN PMXLNODE pNode, // The node to build the graph for
IN ULONG FromNode, // The node's ID
IN ULONG FromNodePin // The Pin connection to look for
);
///////////////////////////////////////////////////////////////////////
//
// BuildNodeTable
//
// Allocates and fills in the table of nodes for the topology.
//
//
PMXLNODE kmxlBuildNodeTable( IN PKSTOPOLOGY pTopology // The topology structure to build from
);
///////////////////////////////////////////////////////////////////////
//
// FindTopologyConnection
//
// Finds the specified connection, if it exists, starting at the
// StartIndex index into the connections table. It will return the
// index into the connection table of a connection starting from
// the given FromNode and FromNodePin. FromNodePin may be PINID_WILDCARD
// if a connection on a node is present rather than a specific connection.
//
//
ULONG kmxlFindTopologyConnection( IN PMIXEROBJECT pmxobj, //IN CONST KSTOPOLOGY_CONNECTION* pConnections, // The connection table
//IN ULONG cConnections, // The # of connections
IN ULONG StartIndex, // Index to start search
IN ULONG FromNode, // The Node ID to look for
IN ULONG FromNodePin // The Pin ID to look for
);
///////////////////////////////////////////////////////////////////////
//
// GetProperty
//
// Retrieves the specified property from an open filter. Flags may
// contain values such as KSPROPERTY_TYPE_TOPOLOGY. The output
// buffer is allocated to the correct size and returned by this
// function.
//
//
NTSTATUS kmxlGetProperty( PFILE_OBJECT pFileObject, // The instance of the filter
CONST GUID *pguidPropertySet, // The requested property set
ULONG ulPropertyId, // The ID of the specific property
ULONG cbInput, // The number of extra input bytes
PVOID pInputData, // Pointer to the extra input bytes
ULONG Flags, // Additional flags
PVOID *ppPropertyOutput // Pointer to a pointer of the output
);
///////////////////////////////////////////////////////////////////////
//
// kmxlNodeProperty
//
// NodeProperty() gets or sets the property on an individual node.
// The output is not allocated and must be passed in by the caller.
// Flags can be KSPROPERTY_TYPE_GET or KSPROPERTY_TYPE_SET.
//
//
NTSTATUS kmxlNodeProperty( IN PFILE_OBJECT pFileObject, // Instance of the filter owning node
IN CONST GUID* pguidPropertySet, // The GUID of the property set
IN ULONG ulPropertyId, // The specific property in the set
IN ULONG ulNodeId, // The virtual node id
IN ULONG cbInput, // # of extra input bytes
IN PVOID pInputData, // Pointer to the extra input bytes
OUT PVOID pPropertyOutput, // Pointer to the output data
IN ULONG cbPropertyOutput, // Size of the output data buffer
IN ULONG Flags // KSPROPERTY_TYPE_GET or SET
);
///////////////////////////////////////////////////////////////////////
//
// kmxlGetNodeProperty
//
// Get the specified property for a node. See kmxlNodeProperty for
// details on parameters and returns.
//
//
#define kmxlGetNodeProperty( pfo,pguid,Id,Node,cbIn,pIn,pOut,cbOut ) \
kmxlNodeProperty( pfo,pguid,Id,Node,cbIn,pIn,pOut,cbOut,KSPROPERTY_TYPE_GET )
///////////////////////////////////////////////////////////////////////
//
// kmxlSetNodeProperty
//
// Sets the specified property for a node. See kmxlNodeProperty for
// details on parameters and returns.
//
//
#define kmxlSetNodeProperty( pfo,pguid,Id,Node,cbIn,pIn,pOut,cbOut ) \
kmxlNodeProperty( pfo,pguid,Id,Node,cbIn,pIn,pOut,cbOut,KSPROPERTY_TYPE_SET )
///////////////////////////////////////////////////////////////////////
//
// kmxlAudioNodeProperty
//
// Sets or get the audio specific node property. The property set
// is always KSPROPSETID_Audio. lChannel specifies which channel to
// apply the property to. 0 is left, 1 is right, -1 is master (all).
// Flags can be either KSPROPERTY_TYPE_GET or KSPROPERTY_TYPE_SET.
//
//
NTSTATUS kmxlAudioNodeProperty( IN PFILE_OBJECT pfo, // Instance of the filter owning node
IN ULONG ulPropertyId, // The audio property to get
IN ULONG ulNodeId, // The virtual node id
IN LONG lChannel, // The channel number
IN PVOID pInData, // Pointer to extra input bytes
IN ULONG cbInData, // Number of extra input bytes
OUT PVOID pOutData, // Pointer to output buffer
IN LONG cbOutData, // Size of the output buffer
IN ULONG Flags // KSPROPERTY_TYPE_GET or SET
);
///////////////////////////////////////////////////////////////////////
//
// kxmlGetAudioNodeProperty
//
// Gets the specified audio property on a node. See kmxlAudioNodeProperty
// for details on parameters and return values.
//
//
#define kmxlGetAudioNodeProperty(pfo,Id,Node,Chan,pIn,cbIn,pOut,cbOut) \
kmxlAudioNodeProperty( pfo,Id,Node,Chan,pIn,cbIn,pOut,cbOut,KSPROPERTY_TYPE_GET )
///////////////////////////////////////////////////////////////////////
//
// kxmlSetAudioNodeProperty
//
// Sets the specified audio property on a node. See kmxlAudioNodeProperty
// for details on parameters and return values.
//
//
#define kmxlSetAudioNodeProperty(pfo,Id,Node,Chan,pIn,cbIn,pOut,cbOut) \
kmxlAudioNodeProperty( pfo,Id,Node,Chan,pIn,cbIn,pOut,cbOut,KSPROPERTY_TYPE_SET )
///////////////////////////////////////////////////////////////////////
//
// kmxlGetPinName
//
// Retrieves the name of the pin given by NodeId.
//
//
VOID kmxlGetPinName( IN PFILE_OBJECT pfo, // Instance of the owning filter
IN ULONG PinId, // Id of the pin
IN PMXLLINE pLine // The line to store the name into
);
///////////////////////////////////////////////////////////////////////
//
// kmxlGetNodeName
//
// Retrieves the name of a node (control).
//
//
VOID kmxlGetNodeName( IN PFILE_OBJECT pfo, // Instance of the owning filter
IN ULONG NodeId, // The node id
IN PMXLCONTROL pControl // The control to store the name
);
///////////////////////////////////////////////////////////////////////
//
// kmxlGetSuperMixCaps
//
//
NTSTATUS kmxlGetSuperMixCaps( IN PFILE_OBJECT pfo, IN ULONG ulNodeId, OUT PKSAUDIO_MIXCAP_TABLE* paMixCaps );
///////////////////////////////////////////////////////////////////////
//
// kmxlQueryPropertyRange
//
//
NTSTATUS kmxlQueryPropertyRange( IN PFILE_OBJECT pfo, IN CONST GUID* pguidPropSet, IN ULONG ulPropertyId, IN ULONG ulNodeId, OUT PKSPROPERTY_DESCRIPTION* ppPropDesc );
///////////////////////////////////////////////////////////////////////
//
// kmxlGetControlChannels
//
//
NTSTATUS kmxlGetControlChannels( IN PFILE_OBJECT pfo, IN PMXLCONTROL pControl );
///////////////////////////////////////////////////////////////////////
//
// kmxlGetControlRange
//
//
NTSTATUS kmxlGetControlRange( IN PFILE_OBJECT pfo, IN PMXLCONTROL pControl );
///////////////////////////////////////////////////////////////////////
//
// kmxlGetNumMuxLines
//
//
DWORD kmxlGetNumMuxLines( IN PKSTOPOLOGY pTopology, IN ULONG NodeId );
///////////////////////////////////////////////////////////////////////
//
// kmxlGetMuxLineNames
//
//
VOID kmxlGetMuxLineNames( IN PMIXEROBJECT pmxobj, IN PMXLCONTROL pControl );
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// M I X E R L I N E F U N C T I O N S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// kmxlBuildDestinationLines
//
// Builds up a list of destination lines given a list of the destination
// nodes.
//
// Returns NULL on error.
//
//
LINELIST kmxlBuildDestinationLines( IN PMIXEROBJECT pmxobj, IN NODELIST listDests // The list of destination nodes
);
///////////////////////////////////////////////////////////////////////
//
// kmxlBuildDestinationControls
//
// Builds a list of mixer line controls for a given destination line.
//
//
NTSTATUS kmxlBuildDestinationControls( IN PMIXEROBJECT pmxobj, IN PMXLNODE pDest, // The destination to built controls for
IN PMXLLINE pLine // The line to add the controls to
);
///////////////////////////////////////////////////////////////////////
//
// kmxlBuildSourceLines
//
// Builds a list of mixer source lines for the given topology.
//
//
LINELIST kmxlBuildSourceLines( IN PMIXEROBJECT pmxobj, IN NODELIST listSources, // The list of source nodes
IN NODELIST listDests // The list of dest. nodes
);
///////////////////////////////////////////////////////////////////////
//
// kmxlBuildPath
//
// Builds the controls for each of the source lines, building new
// source lines of splits are detected in the topology. plistLines
// may have new lines added if splits are encountered. Destinations
// for each of the sources is also determined.
//
//
NTSTATUS kmxlBuildPath( IN PMIXEROBJECT pmxobj, IN PMXLNODE pSource, // The source node for this path
IN PMXLNODE pNode, // The current node in the path
IN PMXLLINE pLine, // The current line
IN OUT LINELIST* plistLines, // The list of lines build so far
IN NODELIST listDests // The list of the destinations
);
///////////////////////////////////////////////////////////////////////
//
// kmxlIsDestinationNode
//
// Return TRUE if the given node appears in the node list of any
// of the destinations in listDests.
//
//
BOOL kmxlIsDestinationNode( IN NODELIST listDests, // The list of destinations
IN PMXLNODE pNode // The node to check
);
///////////////////////////////////////////////////////////////////////
//
// kmxlDuplicateLine
//
// Duplicates the given line, including all controls on that line.
//
//
NTSTATUS kmxlDuplicateLine( IN PMXLLINE* ppTargetLine, // Pointer to the new line
IN PMXLLINE pSourceLine // The line to duplicate
);
///////////////////////////////////////////////////////////////////////
//
// kmxlDuplicateLineControls
//
// Duplicate up to nCount controls on the source line and stores them
// into the target line.
//
//
NTSTATUS kmxlDuplicateLineControls( IN PMXLLINE pTargetLine, // The line to put the controls into
IN PMXLLINE pSourceLine, // The line with the controls to dup
IN ULONG nCount // The number of controls to dup
);
///////////////////////////////////////////////////////////////////////
//
// kmxlFindDestinationForNode
//
// For a given node, this function finds the destination it is assoicated
// with. plistLines needs to be included since new lines will need to
// be created if a split is encountered in the topology.
//
//
ULONG kmxlFindDestinationForNode( IN PMIXEROBJECT pmxobj, IN PMXLNODE pNode, // The node to find dest for
IN PMXLNODE pParent, // The original parent
IN PMXLLINE pLine, // The current line it's on
IN OUT LINELIST* plistLines // The list of all lines
);
///////////////////////////////////////////////////////////////////////
//
// kmxlBuildVirtualMuxLine
//
//
NTSTATUS kmxlBuildVirtualMuxLine( IN PMIXEROBJECT pmxobj, IN PMXLNODE pParent, IN PMXLNODE pMux, IN OUT LINELIST* plistLines );
///////////////////////////////////////////////////////////////////////
//
// kmxlAssignLineAndControlIds
//
// For a specific set of lines, this function assigns the mixer line
// line Ids and controls Ids. Only sources or only destinations can
// be assigned per call.
//
//
NTSTATUS kmxlAssignLineAndControlIds( IN PMIXEROBJECT pmxobj, IN LINELIST listLines, // The list to assign ids for
IN ULONG ListType // LIST_SOURCE or LIST_DESTINATION
);
///////////////////////////////////////////////////////////////////////
//
// kmxlAssignDestinationsToSources
//
// For each line, the destination field of the MIXERLINE structure
// is filled in and a unique LineId is assigned.
//
//
NTSTATUS kmxlAssignDestinationsToSources( IN LINELIST listSourceLines, // The list of all source lines
IN LINELIST listDestLines // The list of all dest lines
);
///////////////////////////////////////////////////////////////////////
//
// kmxlAssignMuxIds
//
//
NTSTATUS kmxlAssignMuxIds( IN PMIXEROBJECT pmxobj, IN LINELIST listSourceLines );
///////////////////////////////////////////////////////////////////////
//
// TranslateNodeToControl
//
// Translates the node specified by its GUID into 0 or more mixer
// line controls. The return value indicates how many controls
// the node was really translated into.
//
//
ULONG kmxlTranslateNodeToControl( IN PMIXEROBJECT pmxobj, IN PMXLNODE pNode, // The node to translate into a control
OUT PMXLCONTROL* ppControl // The control to fill in
);
///////////////////////////////////////////////////////////////////////
//
// kmxlSupportsControl
//
// Queries for property on control to see if it is actually supported
//
//
NTSTATUS kmxlSupportsControl( IN PFILE_OBJECT pfoInstance, // The instance to check for
IN ULONG Node, // The node ID on the instance
IN ULONG Property // The property to query support
);
///////////////////////////////////////////////////////////////////////
//
// kmxlSupportsMultiChannelControl
//
// Queries for property on the second channel of the control to see
// independent levels can be set. It is assumed that the first channel
// already succeeded in kmxlSupportsControl
//
//
NTSTATUS kmxlSupportsMultiChannelControl( IN PFILE_OBJECT pfoInstance, // The instance to check for
IN ULONG Node, // The node id to query
IN ULONG Property // The property to check for
);
///////////////////////////////////////////////////////////////////////
//
// kmxlSupportsTrebleControl
//
// Querys the node to see if it supports KSPROPERTY_AUDIO_TREBLE.
// See kmxlSupportsControl for return value details.
//
//
#define kmxlSupportsTrebleControl( pfo, Node ) \
kmxlSupportsControl( pfo, Node, KSPROPERTY_AUDIO_TREBLE )
///////////////////////////////////////////////////////////////////////
//
// kmxlSupportsBassControl
//
// Querys the node to see if it supports KSPROPERTY_AUDIO_BASS.
// See kmxlSupportsControl for return value details.
//
//
#define kmxlSupportsBassControl( pfo, Node ) \
kmxlSupportsControl( pfo, Node, KSPROPERTY_AUDIO_BASS )
///////////////////////////////////////////////////////////////////////
//
// kmxlUpdateDestinationConnectionCount
//
// Counts the number of sources mapping to a single destination and
// stores that value in the MIXERLINE.cConnections field for that
// destination.
//
//
NTSTATUS kmxlUpdateDestintationConnectionCount( IN LINELIST listSourceLines, // The list of sources
IN LINELIST listDestLines // The list of destinations
);
///////////////////////////////////////////////////////////////////////
//
// kmxlElminiateInvalidLines
//
// Loops through all the lines and eliminates the ones that are
// invalid by the IsValidLine() macro function test.
//
//
NTSTATUS kmxlEliminateInvalidLines( IN LINELIST* listLines // The list of sources
);
///////////////////////////////////////////////////////////////////////
//
// kmxlAssignComponentIds
//
// For each source and destination line, it assignes the
// MIXERLINE.dwComonentType field for that line.
//
//
VOID kmxlAssignComponentIds( IN PMIXEROBJECT pmxobj, // Instance data
IN LINELIST listSourceLines, // The list of source lines
IN LINELIST listDestLines // The list of destination lines
);
///////////////////////////////////////////////////////////////////////
//
// kmxlDetermineDestinationType
//
// Determines the dwComponentId and Target.dwType fields for the
// given line. Determination is made by the MXLLINE.Type field.
//
//
ULONG kmxlDetermineDestinationType( IN PMIXEROBJECT pmxobj, // Instance data
IN PMXLLINE pLine // The line to update
);
///////////////////////////////////////////////////////////////////////
//
// kmxlDetermineSourceType
//
// Determines the dwComponentId and Target.dwType fields for the
// given line. Determination is made by the MXLLINE.Type field.
//
//
ULONG kmxlDetermineSourceType( IN PMIXEROBJECT pmxobj, // Instance data
IN PMXLLINE pLine // The line to update
);
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// U T I L I T Y F U N C T I O N S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// kmxlOpenSysAudio
//
// Opens the SysAudio device and returns the file object.
//
//
PFILE_OBJECT kmxlOpenSysAudio( );
///////////////////////////////////////////////////////////////////////
//
// kmxlCloseSysAudio
//
// Closes the SysAudio device opened by kmxlOpenSysAudio.
//
//
VOID kmxlCloseSysAudio( IN PFILE_OBJECT pfo // The instance to close
);
///////////////////////////////////////////////////////////////////////
//
// kmxlFindDestination
//
// Finds a destination id in the list of all the destinations and returns
// a pointer to that node. Returns NULL on failure.
//
//
PMXLNODE kmxlFindDestination( IN NODELIST listDests, // The list of destinations to search
IN ULONG Id // The node Id to look for in the list
);
///////////////////////////////////////////////////////////////////////
//
// kmxlAppendListToList
//
// Appends listSource onto the front of plistTarget.
//
//
VOID kmxlAppendListToList( IN OUT PSLIST* plistTarget, // The list to append to
IN PSLIST listSource // the list to append
);
///////////////////////////////////////////////////////////////////////
//
// kmxlAppendListToList
//
// Appends listSource onto the end of plistTarget
//
//
VOID kmxlAppendListToEndOfList( IN OUT PSLIST* plistTarget, // The list to append to
IN PSLIST listSource // the list to append
);
///////////////////////////////////////////////////////////////////////
//
// kmxlListCount
//
// Returns the number of elements in the list.
//
//
ULONG kmxlListCount( IN PSLIST pList // The list to count the elements of
);
///////////////////////////////////////////////////////////////////////
//
// kmxlInList
//
// Return TRUE if pNewNode is in the list.
//
//
BOOL kmxlInList( IN PEERLIST list, // The list to search
IN PMXLNODE pNewNode // The new to search for
);
///////////////////////////////////////////////////////////////////////
//
// kmxlAddElemToEndOfList
//
// Adds an element to the end of the given list.
//
//
VOID kmxlAddElemToEndOfList( IN OUT PSLIST* list, // The list to add to the end of
IN PSLIST elem // The element or list to add
);
///////////////////////////////////////////////////////////////////////
//
// kmxlInChildList
//
// Return TRUE if pNewNode is contained in the child list of the list.
//
//
BOOL kmxlInChildList( IN NODELIST list, // The list to search the parent list
IN PMXLNODE pNewNode // The node to search for
);
///////////////////////////////////////////////////////////////////////
//
// kmxlInParentList
//
// Returns TRUE if pNewNode is contained in the parent list of the list.
//
//
BOOL kmxlInParentList( IN NODELIST list, // The list to search the parent list
IN PMXLNODE pNewNode // The node to search for
);
///////////////////////////////////////////////////////////////////////
//
// kmxlSortByDestination
//
// Sorts the given list by destination id in increasing order.
//
//
NTSTATUS kmxlSortByDestination( IN LINELIST* list // The pointer to the list to sort
);
///////////////////////////////////////////////////////////////////////
//
// kmxlVolLinearToLog
//
//
LONG kmxlVolLinearToLog( IN PMXLCONTROL pControl, IN DWORD dwLin, IN MIXERMAPPING Mapping, IN ULONG Channel );
///////////////////////////////////////////////////////////////////////
//
// kmxlVolLogToLinear
//
//
DWORD kmxlVolLogToLinear( IN PMXLCONTROL pControl, IN LONG lLog, IN MIXERMAPPING Mapping, IN ULONG Channel );
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// M E M O R Y A L L O C A T I O N / D E A L L O C A T I O N //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// kmxlAllocMem
//
// Allocates size bytes and stores that pointer in pp. Returns
// STATUS_SUCCESS or another STATUS failure code.
//
//
//NTSTATUS
//kmxlAllocMem(
// IN PVOID *pp, // Pointer to put the new memory in
// IN ULONG size, // The number of bytes to allocate
// IN ULONG ultag
//);
///////////////////////////////////////////////////////////////////////
//
// kmxlAllocDeviceInfo
//
NTSTATUS kmxlAllocDeviceInfo( OUT LPDEVICEINFO *pp, PCWSTR DeviceInterface, DWORD dwFlags, ULONG ultag );
///////////////////////////////////////////////////////////////////////
//
// kmxlFreeMem
//
//
// Frees the memory pointed to by p. Does nothing if p is NULL.
//
//
//VOID
//kmxlFreeMem(
// IN PVOID p // The pointer to the buffer to free
//);
///////////////////////////////////////////////////////////////////////
//
// kmxlFreePeerList
//
// Loops through a peer list freeing all the peer nodes.
//
//
VOID kmxlFreePeerList( IN PEERLIST list // The PeerList to free
);
///////////////////////////////////////////////////////////////////////
//
// kmxlAllocateControl
//
// Allocates and zero fills a new MXLCONTROL structure.
//
//
MXLCONTROL* kmxlAllocateControl( IN ULONG ultag );
VOID kmxlFreeControl( IN PMXLCONTROL pControl );
///////////////////////////////////////////////////////////////////////
//
// kmxlAllocateLine
//
// Allocates and zero filles a new MXLLINE structure.
//
//
MXLLINE* kmxlAllocateLine( IN ULONG ultag );
///////////////////////////////////////////////////////////////////////
//
// kmxlAllocateNode
//
// Allocates and zero filles a new MXLNODE structure.
//
//
MXLNODE* kmxlAllocateNode( IN ULONG ultag );
///////////////////////////////////////////////////////////////////////
//
// kmxlAllocatePeerNode
//
// Allocates and zero fills a new PEERNODE structure.
//
//
PEERNODE* kmxlAllocatePeerNode( IN PMXLNODE pNode OPTIONAL, // The node to associate with the peer
IN ULONG ultag );
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// P E R S I S T A N C E F U N C T I O N S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
NTSTATUS kmxlOpenInterfaceKey( IN PFILE_OBJECT pfo, IN ULONG Device, OUT HANDLE* phKey );
NTSTATUS kmxlRegQueryValue( IN HANDLE hKey, IN PWCHAR szValueName, IN PVOID pData, IN ULONG cbData, OUT PULONG pResultLength );
///////////////////////////////////////////////////////////////////////
//
// kmxlRegCloseKey
//
// Closes the given key and NULLs the pointer.
//
//
#define kmxlRegCloseKey( hKey ) \
{ \ ZwClose( hKey ); \ hKey = NULL; \ }
///////////////////////////////////////////////////////////////////////
//
// PinCategoryToString
//
// Translates a PinCategory GUID into a string.
//
//
const char* PinCategoryToString ( IN CONST GUID* NodeType // The node to translate
);
///////////////////////////////////////////////////////////////////////
//
// NodeTypeToString
//
// Translates a NodeType GUID to a string.
//
//
const char* NodeTypeToString ( IN CONST GUID* NodeType // The node to translate
);
#define ControlTypeToString( dwType ) \
(dwType) == MIXERCONTROL_CONTROLTYPE_BOOLEAN ? "Boolean" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_ONOFF ? "On Off" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_MUTE ? "Mute" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_MONO ? "Mono" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_LOUDNESS ? "Loudness" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_STEREOENH ? "Stereo Enhance" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_VOLUME ? "Volume" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_BASS ? "Bass" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_TREBLE ? "Treble" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_BASS_BOOST ? "Bass Boost" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_PEAKMETER ? "Peakmeter" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_MUX ? "Mux" : \ (dwType) == MIXERCONTROL_CONTROLTYPE_MIXER ? "Mixer" : \ "Unknown ControlType"
///////////////////////////////////////////////////////////////////////
//
// ComponentTypeToString
//
// Translates one of the MIXERLINE_COMPONENTTYPE constants to a string.
//
//
#define ComponentTypeToString( dwType ) \
(dwType) == MIXERLINE_COMPONENTTYPE_DST_DIGITAL ? "Digital line" : \ (dwType) == MIXERLINE_COMPONENTTYPE_DST_HEADPHONES ? "Headphones" : \ (dwType) == MIXERLINE_COMPONENTTYPE_DST_LINE ? "Line" : \ (dwType) == MIXERLINE_COMPONENTTYPE_DST_MONITOR ? "Monitor" : \ (dwType) == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS ? "Speakers" : \ (dwType) == MIXERLINE_COMPONENTTYPE_DST_TELEPHONE ? "Telephone" : \ (dwType) == MIXERLINE_COMPONENTTYPE_DST_UNDEFINED ? "Undefined" : \ (dwType) == MIXERLINE_COMPONENTTYPE_DST_VOICEIN ? "Voicein" : \ (dwType) == MIXERLINE_COMPONENTTYPE_DST_WAVEIN ? "Wavein" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_ANALOG ? "Analog line" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY ? "Auxiliary" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC ? "Compact disc" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_DIGITAL ? "Digital line" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_LINE ? "Line" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE ? "Microphone" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER ? "PC Speaker" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER ? "Synthesizer" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE ? "Telephone" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED ? "Undefined" : \ (dwType) == MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT ? "Waveout" : \ "Unknown ComponentType"
///////////////////////////////////////////////////////////////////////
//
// TargetTypeToString
//
// Translates one of hte MIXERLINE_TARGETTYPE constants to a string.
//
//
#define TargetTypeToString( dwType ) \
(dwType) == MIXERLINE_TARGETTYPE_AUX ? "Aux" : \ (dwType) == MIXERLINE_TARGETTYPE_MIDIIN ? "MidiIn" : \ (dwType) == MIXERLINE_TARGETTYPE_MIDIOUT ? "MidiOut" : \ (dwType) == MIXERLINE_TARGETTYPE_UNDEFINED ? "Undefined" : \ (dwType) == MIXERLINE_TARGETTYPE_WAVEIN ? "WaveIn" : \ (dwType) == MIXERLINE_TARGETTYPE_WAVEOUT ? "WaveOut" : \ "Unknown TargetType"
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// //
// D E B U G O N L Y F U N C T I O N S //
// //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
#ifdef DEBUG
///////////////////////////////////////////////////////////////////////
//
// LineFlagsToString
//
// Converts on of the MIXERLINE_LINEF flags to a string.
//
//
#define LineFlagsToString( fdwFlags ) \
( fdwFlags & MIXERLINE_LINEF_ACTIVE ) ? "ACTIVE " : \ ( fdwFlags & MIXERLINE_LINEF_DISCONNECTED ) ? "DISCONNECTED " : \ ( fdwFlags & MIXERLINE_LINEF_SOURCE ) ? "SOURCE " : \ "Unknown"
///////////////////////////////////////////////////////////////////////
//
// DumpChildGraph
//
// For a given node, it dumps the child of that node onto the debug
// monitor. CurrentIndent is the number of spaces to indent before
// display.
//
//
VOID DumpChildGraph( IN PMXLNODE pNode, // The node to display the children of
IN ULONG CurrentIndent // The number of spaces to ident
);
///////////////////////////////////////////////////////////////////////
//
// DumpMemList
//
// Dumps the list of currently allocated memory blocks.
//
//
VOID DumpMemList( );
#endif // DEBUG
VOID GetHardwareEventData(LPDEVICEINFO pDeviceInfo);
#endif // _MIXER_H_INCLUDED
|