windows-nt/Source/XPSP1/NT/drivers/wdm/audio/legacy/wdmaud.sys/mixer.h

1654 lines
51 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//---------------------------------------------------------------------------
//
// 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