Windows Platform Design Notes
Design Information for the Microsoft® Windows® Family of Operating Systems
DirectKS Sample Application
This document provides information about WDM audio drivers for the Microsoft® Windows® family of operating systems. It presents guidelines for writing audio-authoring applications that need to directly access audio drivers to reduce latency.
Send feedback about the DirectKS sample code and documentation to directks@microsoft.com.
Building on Visual Studio .NET
DirectKS Filter and Pin Proxy Classes
CKsAudCapFilter::CKsAudCapFilter
CKsAudCapFilter::CreateCapturePin
CKsAudCapFilter::GetCapturePin
CKsAudRenFilter::CKsAudRenFilter
CKsAudRenFilter::CanCreateRenderPin
CKsAudRenFilter::CreateRenderPin
CKsFilter::GetPinPropertyMulti
CKsFilter::GetPinPropertySimple
CKsPin::HasDataRangeWithSpecifier
CKsEnumFilters::CKsEnumFilters
This
is a preliminary document and may be changed substantially prior to final
public release. This document is provided for informational purposes only and
Microsoft makes no warranties, either expressed or implied, in this document.
Information in this document, including URL and other Internet Web site
references, is subject to change without notice. The entire risk of the use or
the results of the use of this document remains with the user. Unless otherwise
noted, the example companies, organizations, products, people and events
depicted herein are fictitious and no association with any real company,
organization, product, person or event is intended or should be inferred.
Complying with all applicable copyright laws is the responsibility of the user.
Without limiting the rights under copyright, no part of this document may be
reproduced, stored in or introduced into a retrieval system, or transmitted in
any form or by any means (electronic, mechanical, photocopying, recording, or
otherwise), or for any purpose, without the express written permission of
Microsoft Corporation.
Microsoft
does not make any representation or warranty regarding specifications in this
document or any product or item developed based on these specifications.
Microsoft disclaims all express and implied warranties, including but not
limited to the implied warranties or merchantability, fitness for a particular
purpose and freedom from infringement. Without limiting the generality of the
foregoing, Microsoft does not make any warranty of any kind that any item
developed based on these specifications, or any portion of a specification,
will not infringe any copyright, patent, trade secret or other intellectual
property right of any person or entity in any country. It is your
responsibility to seek licenses for such intellectual property rights where
appropriate. Microsoft shall not be liable for any damages arising out of or in
connection with the use of these specifications, including liability for lost
profit, business interruption, or any other damages whatsoever. Some states do
not allow the exclusion or limitation of liability or consequential or
incidental damages; the above limitation may not apply to you.
The
information contained in this document represents the current view of Microsoft
Corporation on the issues discussed as of the date of publication. Because
Microsoft must respond to changing market conditions, it should not be
interpreted to be a commitment on the part of Microsoft, and Microsoft cannot
guarantee the accuracy of any information presented. This document is for
informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED,
IN THIS DOCUMENT.
Microsoft,
Windows, and Windows NT are trademarks or registered trademarks of Microsoft
Corporation in the
©
2002 Microsoft Corporation. All rights reserved.
The DirectKS sample application program demonstrates how a user-mode client can achieve direct access to kernel streaming (KS) filters. The sample application plays a wave audio stream through an audio-rendering device. However, with relatively little effort, the application can be modified to record a wave audio stream from an audio-capture device. The classes that are implemented in the sample code support both audio rendering and capture.
The DirectKS approach should be used only by applications with special requirements (such as low latency) that preclude using one of the standard audio APIs to play or record wave audio data. Most audio applications should use DirectSound® or the waveOut and waveIn APIs instead.
However, for operating systems such as Microsoft® Windows® 2000, Windows XP, and Windows .NET Server 2003, ISVs must contend with an audio subsystem that adds a minimum of 30 milliseconds of output latency to an audio stream. For these operating systems, the truly latency-focused ISV may find it worthwhile to write extra code to bypass the existing multimedia APIs and communicate directly with the audio driver. The DirectKS sample illustrates a simple application that uses the SetupDi API and KS property IOCTLs to discover and open KS filters and pins on a WDM audio driver, and to stream audio data to the KS pin in a direct manner.
Note
Using the DirectKS approach results in exclusive access to the audio device, which can break many aspects of the user experience, including disabling warning alert sounds and loss of interoperability with other audio applications. For this reason, the Windows multimedia team actively discourages the direct use of KS properties in applications that do not require such low-level control. For applications that do need this low-level control, the application should relinquish control of the device when the application is not the foreground process and is not actively streaming. The sample code illustrates one possible implementation of this guideline.
The Microsoft Windows audio team is working hard to reduce overall audio latency in future Windows operating systems. An important part of this effort is to provide low-latency implementations of audio APIs in order to eliminate any need to access the KS audio components directly.
The plan for future Windows releases is to provide built-in multimedia APIs and core services with very low latency and complete bit-for-bit transparency. These features should eliminate the need for any application program to circumvent the audio subsystem. The IOCTL requests used by the sample application rely on internal aspects of the current architecture that are likely to change in future operating systems, including the next version of Windows, codenamed Windows "Longhorn." Be forewarned that the DirectKS approach is unlikely to work on operating systems after Windows XP and Windows .NET Server.
At the core of the Windows platform is a powerful kernel architecture incorporating kernel streaming (KS) and the Windows driver model (WDM). KS and WDM provide robust features for transporting and processing audio and video streams. Another feature of this architecture is a kernel system mixer (KMixer) that combines audio streams from concurrently running applications into a single stream that plays through the speakers. KMixer allows users to hear audible cues such as email announcements and critical error notifications while using a different application, for example, to play back their favorite WMA or MP3 file. KMixer also serves as the real-time audio mixer for interactive applications like games and edutainment titles, and provides such services as sample-rate conversion, multi-stream mixing, format conversion, and 3D audio processing.
For the vast majority of media applications (for example, games, media playback applications, and WMA and MP3 players), KMixer provides exactly the desired behavior and functionality: system-wide mixing, plus efficient real-time software-based format conversion and mixing for interactive applications. These applications utilize user-mode APIs that expose the features of the kernel implementation through high-level APIs that are easy to use. Currently, all user-mode Windows audio APIs (DirectSound, waveOut, and so on) insert KMixer between the audio hardware filter pins and the applications themselves in order to achieve system-wide mixing.
However, audio-authoring applications represent a category of application programs that do not require and are not entirely compatible with KMixer. These applications require direct access to whatever sound hardware is on the user's system. To avoid unwanted latency, these applications need their audio signals to bypass KMixer or other system components that do signal processing.
The DirectKS sample implements a set of user-mode functions designed to allow applications—particularly audio-authoring applications—to access the hardware device directly, thus bypassing the audio stack that is constructed for typical Windows applications. It allows a user-mode application to enumerate KS filters and communicate with them. An application can access the audio device, as exposed by its miniport driver, directly. This type of direct access to the hardware is ideally suited for high-end audio hardware and associated software requiring a direct pipe from the user-mode application to the audio outputs on the hardware.
The DirectKS sample illustrates the direct use of the KS audio system by a user-mode application program to perform audio rendering. At the highest level of abstraction, the sample illustrates the following:
1. Enumeration of KS filters
2. Use of KS filters for streaming
The sample application uses the Setup APIs to enumerate the KS filters. No new major concepts are introduced by this sample, and the code should be largely self-explanatory. For these reasons, this document focuses on the second item: the use of KS filters for streaming audio data. Because this is only sample code, the document does not provide a detailed treatment of the code, but instead highlights the concepts illustrated by the code. The code and supporting comments should help to clarify details not covered in this document.
The DirectKS sample uses the following Win32® APIs:
The Setup API functions for enumerating installed KS filters.
The KsCreatePin function for the creation of KS pin objects.
The DeviceIoControl function for filter and pin properties and events, as well as for data streaming.
Streaming data to or from a KS filter involves the following steps:
1. Instantiate the filter.
2. Instantiate a pin, which requires that you specify the format of the data that you want to stream.
3. Prepare each data buffer by filling out a KSSTREAM_HEADER structure describing the buffer’s size and time stamps, and an OVERLAPPED structure with a valid event handle.
4. Set the pin to a state in which it can accept data packets, namely KSSTATE_PAUSE or KSSTATE_RUN.
5. Submit the KSSTREAM_HEADER and OVERLAPPED structures by calling DeviceIoControl with the dwIoControlCode parameter specified as IOCTL_KS_WRITE or IOCTL_KS_READ.
6. If the pin is not already in the run state, set the pin's state to KSSTATE_RUN.
The OVERLAPPED structure is necessary to perform asynchronous I/O. After the data is submitted, the audio driver uses the handle in the OVERLAPPED structure to signal when the data has been consumed (in the rendering case) or when the data buffer has been filled (in the capture case). Because the I/O is performed asynchronously, you can submit multiple packets of data at a time and then monitor the completion status of the individual packets. An application typically creates an array or queue of data buffers, each with its own pair of KSSTREAM_HEADER and OVERLAPPED structures. The application reuses these packets as they become available again on completion of the event signaled by the OVERLAPPED.hEvent handle. The DirectKS sample code demonstrates a solution that uses a pool of four data buffers.
When rendering, the application fills out the KSSTREAM_HEADER structure before submitting the write request. The DataUsed member of KSSTREAM_HEADER should specify the size of the data buffer used for rendering. In the capture case, the application initializes DataUsed to zero, and the capture pin fills this member in with the actual number of bytes used when it handles the read request.
The wave-descriptor structure WAVEFORMATEX is obsolete and has been replaced by WAVEFORMATEXTENSIBLE, which can adequately describe wave formats with sample sizes greater than 16 bits and with more than two channels. Because some older drivers are able to handle only WAVEFORMATEX, however, the DirectKS sample code is designed to deal with both WAVEFORMATEX and WAVEFORMATEXTENSIBLE. For more information on these two structures, see the Windows DDK documentation.
The DirectKS sample directory contains the Visual C++® source files listed in the following table.
Source File |
Description |
audfilter.cpp |
Implementation of classes CKsAudFilter, CKsAudRenFilter, and CKsAudCapFilter. |
audfilter.h |
Header file for classes CKsAudFilter, CKsAudRenFilter, and CKsAudCapFilter. |
audpin.cpp |
Implementation of classes CKsAudPin, CKsAudRenPin, and CKsAudCapPin. |
audpin.h |
Header file for classes CKsAudPin, CKsAudRenPin, and CKsAudCapPin. |
enum.cpp |
Implementation of class CKsEnumFilters. |
enum.h |
Header file for class CKsEnumFilters. |
filter.cpp |
Implementation of class CKsFilter. |
filter.h |
Header file for class CKsFilter. |
irptgt.cpp |
Implementation of class IrpTarget. |
irptgt.h |
Header file for class IrpTarget. |
kssample.cpp |
Implementation of sample application program. |
kssample.h |
Header file for sample application program. |
node.cpp |
Implementation of class CKsNode. |
node.h |
Header file for class CKsNode. |
pin.cpp |
Implementation of class CKsPin. |
pin.h |
Header file for class CKsPin. |
resource.h |
Resource ID constants used by sample application. |
tlist.h |
Header file for TList class template. |
util.cpp |
Implementation of general helper functions. |
util.h |
Header file for general helper functions. |
The DirectKS sample code is written in Visual C++® and builds on either Visual Studio® 6.0 or Visual Studio .NET.
To build the project on Visual Studio 6.0, do the following:
1. From the main menu, select File -> Open Workspace, browse to the DirectKS sample directory, and open VC++ workspace file kssample.dsw.
2. From the main menu, select Build -> Build kssample.exe.
If Visual Studio 6.0 is unable to build the sample because it cannot find the SDK include files or libraries, do the following:
1. From the menu, select Tools -> Options and click on the Directories tab.
2. Under the label Show directories for, select Include files and type in the SDK include path under Directories. (You might want to move this path to the top of the list.)
3. Under the label Show directories for, select Library files and type in the SDK library path under Directories. (Again, you might want to move this path to the top of the list.)
Now try building the project again.
To build the project on Visual Studio .NET, do the following:
1. From the main menu, select File -> Open -> Project, and double-click on the VC++ 6 project file, kssample.dsp.
2. If you see a pop-up window that says, "The project kssample.dsp needs to be converted...Do you want to convert?", answer "Yes".
3. From the main menu, select Build -> Build Solution. In the Save File As pop-up window, save the Visual Studio solution file ksstate.sln.
To run the sample (outside of Visual Studio), browse to the sample directory and run the executable file Debug\kssample.exe. You should see the KS sample app window appear.
From the sample application's main menu, select Pin State -> KSSTATE_RUN. You should hear a steady tone. (The application plays a wave buffer containing a continuous sine wave.)
Move the cursor outside the window and click. The tone should stop as the application loses focus.
You will see status messages appear in the sample application window as you follow the preceding steps.
When the user selects one of the sample application's menu items, the WndProc function in kssample.cpp receives a WM_COMMAND Windows message. This function determines whether the command is to exit the application or to change the pin state to stop, pause, or run. In each case, it signals the appropriate event. The signaled event is handled by the RenderThreadProc function (also in kssample.cpp), which uses the WaitForMultipleObjects Win32 call to monitor these events.
When the window is created, or when the window gains or loses focus, the WndProc function receives a WM_ACTIVATEAPP Windows message. The function checks to see whether the application is gaining focus or losing focus. If it is losing focus, it signals an event that tells the application to abort the thread that is playing the audio stream. Again, the RenderThreadProc function uses the WaitForMultipleObjects call to monitor the event. If the window is either gaining focus or is being created, WndProc calls the CreateRenderThread function, which creates a thread that plays the audio stream. This thread executes the RenderThreadProc function.
If you want to step through the sample application code with a debugger, a good place to begin is with the RenderThreadProc function. By setting a breakpoint to the beginning of this function and stepping through it, you will see that it does the following:
Enumerates audio rendering filters.
Creates an instance of one of these filters.
Enumerates the pins in the filter instance.
Creates an instance of one of these pins.
The main loop in the function plays the wave data through the pin instance. The wave data is contained in four buffers. Each time the pin finishes playing a buffer, it signals the event associated with that buffer. Within the loop, the RenderThreadProc function uses the WaitForMultipleObjects call to monitor these events (as well as the abort, stop, pause, and run events discussed earlier). When the event indicates that the pin has finished with the buffer, the loop fills the buffer with more audio data and calls CKsPin::WriteData to play the buffer's new data.
When the application's window loses focus and the WndProc function signals the abort event, the RenderThreadProc routine exits, terminating the playback thread.
The DirectKS sample demonstrates how to communicate with kernel-mode objects such as KS filters and pins. Instead of communicating directly with these kernel-mode objects, however, the DirectKS sample application creates proxy objects that manage the kernel-mode objects from user mode. These proxies present a simplified interface to the application. They hide many of the details of I/O operations such as property requests, events, and data streaming.
The following is the class hierarchy for filter and pin proxy objects:
CKsIrpTarget
CKsFilter
CKsAudFilter
CKsAudRenFilter
CKsAudCapFilter
CKsPin
CKsAudPin
CKsAudCapPin
CKsAudRenPin
The object hierarchy in DirectKS maps to the conceptual objects that make up DirectKS. The most basic objects are KS filters and pins, which are represented by the base classes CKsFilter and CKsPin. Both of these classes derive from a base class CKsIrpTarget that abstracts functionality that is common to both filters and pins. Additional classes are derived from these base classes to handle specific types of filters and pins with specific data formats. For example, CKsAudFilter, which represents an audio filter, serves as the base class for CKsAudRenFilter and CKsAudCapFilter, which represent audio-rendering and audio-capture filters, respectively.
Note that creating a CKsFilter or CKsPin object does not necessarily create an instance of the underlying KS filter or pin. For example, the CKsEnumFilters::EnumFilters function has a call parameter named fInstantiate that indicates whether to instantiate the underlying KS filters at the time that the function creates the CKsFilter objects for the enumerated filters. An application program cannot send IRPs to a filter or pin until the filter or pin has been instantiated. Thus, a CKsFilter or CKsPin object whose filter or pin is not instantiated is unable to send property requests to the filter or pin. When creating an instance of a KS filter or pin, a CKsFilter or CKsPin object receives from the operating system a filter or pin handle that it uses to identify the KS filter or pin in subsequent operations. The CKsFilter or CKsPin object retains this handle until it closes the KS filter or pin.
User-mode proxy objects for KS filters and pins are implemented with the following classes:
These classes are described in the following sections.
The CKsAudCapFilter class encapsulates an audio-capture filter. CKsAudCapFilter is derived from base class CKsAudFilter.
This class is defined in header file audfilter.h in the sample directory.
In addition to the members inherited from base class CKsAudFilter, CKsAudCapFilter contains the following public members:
CKsAudCapFilter::CKsAudCapFilter
CKsAudCapFilter::CreateCapturePin
CKsAudCapFilter::GetCapturePin
These members are described in the following sections.
The CKsAudCapFilter constructor creates and initializes an object of type CKsAudCapFilter.
CKsAudCapFilter (
LPCTSTR pszName,
HRESULT *phr
);
Parameters
pszName
Pointer to a NULL-terminated character string that contains the KS filter's device-interface path name. This path name can be passed to Win32 functions such as CreateFile. For more information, see the description of the SP_DEVICE_INTERFACE_DETAIL_DATA structure in the Windows DDK documentation.
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
A DirectKS application program typically does not use this constructor. Instead, it indirectly creates CKsAudCapFilter objects for a list of capture filters by calling CKsEnumFilters::EnumFilters.
See Also
The CreateCapturePin member function creates an audio-capture pin.
CKsAudCapPin*
CreateCapturePin (
WAVEFORMATEX *pwfx,
BOOL fLooped
);
Parameters
pwfx
Pointer to wave-format descriptor. This descriptor is a structure of type WAVEFORMATEX or WAVEFORMATEXTENSIBLE describing the data format for a wave stream. For more information, see the descriptions of WAVEFORMATEX and WAVEFORMATEXTENSIBLE in the Windows DDK documentation.
fLooped
Specifies whether the capture buffer is looped. If TRUE, the buffer is looped. If FALSE, it is not looped. If the pin provides looped buffering, then when the pin's buffer pointer reaches the end of the buffer, it automatically wraps to the start of the buffer. In the case of a nonlooped buffer, the pin processes a capture buffer only once and is finished with the buffer when it reaches the buffer's end. For more information about looped and nonlooped buffers, see the descriptions of the KSINTERFACE_STANDARD_LOOPED_STREAMING and KSINTERFACE_STANDARD_STREAMING interfaces in the Windows DDK documentation.
Return Value
CreateCapturePin returns a pointer to the newly created capture pin, which is an object of type CKsAudCapPin.
Comments
This function creates an audio-capture pin that can process audio data in the format specified by the pwfx parameter. The function fails if the filter is unable to instantiate a pin that can handle this format.
CreateCapturePin creates an instance of the pin and receives a pin handle from the kernel, which the CKsAudCapPin object keeps as part of its internal state.
When selecting a pin from the CKsAudCapFilter object's list of pins, CreateCapturePin chooses the first viable capture pin that it finds and creates an instance of that pin. This pin is not necessarily the best pin in the list for capturing data in the specified format.
See Also
The GetCapturePin member function retrieves a pointer to the CKsAudCapPin object for a capture pin.
HRESULT
GetCapturePin (
CKsAudCapPin **ppPin
);
Parameters
ppPin
Pointer to a caller-allocated pointer variable into which the function writes the pointer to a CKsAudCapPin object.
Return Value
GetCapturePin returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
This function retrieves a pointer to the first item in the filter's list of CKsAudCapPin objects for capture pins. The function does not remove the object from the list, and the caller should not attempt to delete this object directly. The object pointer remains valid as long as the CKsAudCapFilter object exists.
After obtaining a pointer to the CKsAudCapPin object, the caller can call the member functions on this object to determine which formats the pin supports and, if necessary, to create an instance of the pin by calling CKsPin::Instantiate.
See Also
CKsAudCapPin, CKsPin::Instantiate
The CKsAudCapPin class encapsulates an audio-capture pin. CKsAudCapPin is derived from base class CKsAudPin.
This class is defined in header file audpin.h in the sample directory.
In addition to the members inherited from base class CKsAudPin, CKsAudCapPin contains the following public member:
This member is described in the following section.
The CKsAudCapPin constructor creates and initializes an object of type CKsAudCapPin.
CKsAudCapPin (
CKsAudFilter *pFilter,
ULONG nId,
HRESULT *phr
);
Parameters
pFilter
Pointer to the CKsAudFilter object for the filter that the pin is attached to.
nId
Specifies the pin ID. This parameter identifies a pin factory within the target filter. If the filter contains n pin factories, valid pin IDs range from 0 to n-1.
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function writes S_OK. Otherwise, it writes an appropriate error code.
Comments
A DirectKS application program typically does not use this constructor. Instead, it indirectly creates a CKsAudCapPin object for a capture pin by calling CKsAudFilter::EnumeratePins.
See Also
The CKsAudFilter class encapsulates an audio filter. CKsAudFilter is derived from base class CKsFilter. Classes CKsAudRenFilter and CKsAudCapFilter are both derived from CKsAudFilter.
This class is defined in header file audfilter.h in the sample directory.
For the most part, the classes derived from CKsFilter just provide specific implementations of methods declared as virtual in the base class. The exception is CKsAudFilter, which has special WAVEFORMATEX-specific member functions for enumerating and instantiating pins.
In addition to the members inherited from base class CKsFilter, CKsAudFilter contains the following public member:
This member is described in the following section.
The EnumeratePins member function enumerates the pins in the audio filter.
virtual HRESULT
EnumeratePins (
void
);
Parameters
None
Return Value
EnumeratePins returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
This function enumerates pins on the filter and sorts them into one or more of the pin lists that are part of the CKsAudFilter object's internal state.
Application programs typically do not call this function. Instead, applications call the CKsEnumFilters::EnumFilters function, which enumerates the pins in each filter that it enumerates.
The process of enumerating the pins in an audio filter instance consists of the following steps:
1. Querying the filter for the number of pin types that the filter supports. For each pin type, the filter contains a pin factory that creates pin instances of that type.
2. Querying each pin factory in the filter for the properties that its pin type supports. These properties specify whether the pin performs audio rendering or capture.
The EnumeratePins function creates a CKsAudRenPin or CKsAudCapPin object for each audio rendering or capture pin type that the filter supports. The function builds a list of these objects, which the CKsAudFilter object maintains as part of its the internal state.
See Also
CKsEnumFilters::EnumFilters , CKsAudRenPin, CKsAudCapPin
The CKsAudPin class encapsulates an audio pin. CKsAudPin is derived from base class CKsPin.
This class is defined in header file audpin.h in the sample directory.
In addition to the members inherited from base class CKsPin, CKsAudPin contains the following public members:
These members are described in the following sections.
The CKsAudPin constructor creates and initializes an object of type CKsAudPin.
CKsAudPin (
CKsAudFilter *pFilter,
ULONG nId,
HRESULT *phr
);
Parameters
pFilter
Pointer to the CKsAudFilter object for the KS filter that the pin belongs to.
nId
Specifies the pin ID. This parameter identifies a pin factory within the target filter. If the filter contains n pin factories, valid pin IDs range from 0 to n-1.
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
A DirectKS application program typically does not use this constructor. Instead, it indirectly creates a CKsAudCapPin or CKsAudRenPin object for a capture or rendering pin by calling CKsAudCapFilter::CreateCapturePin or CKsAudRenFilter::CreateRenderPin.
See Also
CKsAudFilter, CKsAudCapFilter::CreateCapturePin, CKsAudRenFilter::CreateRenderPin
The GetFormat member function gets the audio pin's current wave format.
const WAVEFORMATEX*
GetFormat(
void
);
Parameters
None
Return Value
GetFormat returns a pointer to a WAVEFORMATEX or WAVEFORMATEXTENSIBLE structure specifying the pin's current format. This pointer remains valid as long as the CKsAudPin object exists or until the CKsAudPin::SetFormat function is called. For more information, see the descriptions of WAVEFORMATEX and WAVEFORMATEXTENSIBLE in the Windows DDK documentation.
See Also
The GetPosition member function returns the pin's current write and play positions as byte offsets from the beginning of the stream.
HRESULT
GetPosition (
KSAUDIO_POSITION *Pos
);
Parameters
Pos
Pointer to a KSAUDIO_POSITION structure into which the function writes the current write and play positions. Both positions are expressed as byte offsets from the beginning of the stream. For more information, see the description of KSAUDIO_POSITION in the Windows DDK documentation.
Return Value
GetPosition returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
The IsFormatSupported member function indicates whether the audio pin supports a particular data format.
BOOL
IsFormatSupported (
const WAVEFORMATEX *pwfx
);
Parameters
pwfx
Pointer to wave-format descriptor. This descriptor is a structure of type WAVEFORMATEX or WAVEFORMATEXTENSIBLE describing the data format for a wave stream. For more information, see the descriptions of WAVEFORMATEX and WAVEFORMATEXTENSIBLE in the Windows DDK documentation.
Return Value
IsFormatSupported returns TRUE if the audio pin supports the specified data format. Otherwise, it returns FALSE.
Comments
A DirectKS application program calls this function to determine whether a pin supports a particular data format for the wave stream that passes through the pin.
The m_listDataRange member is a list of the data ranges that the pin supports.
TList<KSDATARANGE_AUDIO> m_listDataRange;
Comments
Each item in the list contains a pointer to a KSDATARANGE_AUDIO structure that specifies a range of data formats that the audio pin supports. The CKsAudPin constructor creates this list.
Through this member, the application can directly access the pin's list of supported data ranges. See TList for a description of the operations that the application can perform on the list.
See Also
The SetFormat member function sets the pin's current wave format.
HRESULT
SetFormat (
const WAVEFORMATEX *pwfx
);
Parameters
pwfx
Pointer to wave-format descriptor. This descriptor is a structure of type WAVEFORMATEX or WAVEFORMATEXTENSIBLE describing the data format for a wave stream. For more information, see the description of WAVEFORMATEX and WAVEFORMATEXTENSIBLE in the Windows DDK documentation.
Return Value
SetFormat returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
Call this function to specify the stream format for a pin before calling CKsPin::Instantiate to instantiate the pin.
SetFormat has no effect on a pin that has already been instantiated.
See
Also
The SetPosition member function specifies the pin's new write and play positions as byte offsets from the beginning of the stream.
HRESULT
SetPosition (
KSAUDIO_POSITION *Pos
);
Parameters
Pos
Pointer to a KSAUDIO_POSITION structure that specifies the new read and write positions, which are expressed as byte offsets from the beginning of the stream. For more information, see the description of KSAUDIO_POSITION in the Windows DDK documentation.
Return Value
SetPosition returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
The CKsAudRenFilter class encapsulates an audio-rendering filter. CKsAudRenFilter is derived from base class CKsAudFilter.
This class is defined in header file audfilter.h in the sample directory.
In addition to the members inherited from base class CKsAudFilter, CKsAudRenFilter contains the following public members:
CKsAudRenFilter::CKsAudRenFilter
CKsAudRenFilter::CanCreateRenderPin
CKsAudRenFilter::CreateRenderPin
These members are described in the following sections.
The CKsAudRenFilter constructor creates and initializes an object of type CKsAudRenFilter.
CKsAudRenFilter (
LPCTSTR pszName,
HRESULT *phr
);
Parameters
pszName
Pointer to a NULL-terminated character string that contains the KS filter's device-interface path name. This path name can be passed to Win32 functions such as CreateFile. For more information, see the description of the SP_DEVICE_INTERFACE_DETAIL_DATA structure in the Windows DDK documentation.
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
A DirectKS application program typically does not use this constructor. Instead, it indirectly creates CKsAudRenFilters objects for a list of rendering filters by calling CKsEnumFilters::EnumFilters.
See Also
The CanCreateRenderPin member function indicates whether the filter can create a pin that is able to process a stream with the specified wave format.
BOOL
CanCreateRenderPin (
const WAVEFORMATEX *pwfx
);
Parameters
pwfx
Pointer to wave-format descriptor. This descriptor is a structure of type WAVEFORMATEX or WAVEFORMATEXTENSIBLE describing the data format for a wave stream. For more information, see the descriptions of WAVEFORMATEX and WAVEFORMATEXTENSIBLE in the Windows DDK documentation.
Return Value
CanCreateRenderPin returns TRUE if the filter can create a rendering pin to process a stream with the specified wave format. Otherwise, it returns FALSE.
The CreateRenderPin member function creates a rendering pin.
CKsAudRenPin*
CreateRenderPin (
const
WAVEFORMATEX *pwfx,
BOOL fLooped
);
Parameters
pwfx
Pointer to wave-format descriptor. This descriptor is a structure of type WAVEFORMATEX or WAVEFORMATEXTENSIBLE describing the data format for a wave stream. For more information, see the descriptions of WAVEFORMATEX and WAVEFORMATEXTENSIBLE in the Windows DDK documentation.
fLooped
Specifies whether the render buffer is looped. If TRUE, the buffer is looped. If FALSE, the buffer is not looped. If the pin provides looped buffering, then when the pin's buffer pointer reaches the end of the buffer, it automatically wraps to the start of the buffer. In the case of a nonlooped buffer, the pin processes a render buffer only once and is finished with the buffer when it reaches the buffer's end.
Return Value
CreateRenderPin returns a pointer to a CKsAudRenPin object if it succeeds in creating the object. Otherwise, it returns NULL.
Comments
This function creates a rendering pin that can process audio data in the format specified by the pwfx parameter. The function fails if the filter is unable to instantiate a pin that can handle this format.
CreateRenderPin instantiates the KS pin and retrieves a pin handle from the operating system. The CKsAudRenPin object retains this handle as part of its internal state.
When selecting a pin from the CKsAudRenFilter object's list of pins, CreateRenderPin chooses the first viable rendering pin that it finds and creates an instance of that pin. This pin is not necessarily the best pin in the list for rendering data in the specified format.
See Also
The CKsAudRenPin class encapsulates an audio-rendering pin. CKsAudRenPin is derived from base class CKsAudPin.
This class is defined in header file audpin.h in the sample directory.
In addition to the members inherited from base class CKsAudPin, CKsAudRenPin contains the following public member:
This member is described in the following section.
The CKsAudRenPin constructor creates and initializes an object of type CKsAudRenPin.
CKsAudRenPin (
CKsAudFilter *pFilter,
ULONG nId,
HRESULT *phr
);
Parameters
pFilter
Pointer to the CKsAudFilter object for the KS filter that the pin belongs to.
nId
Specifies the pin ID. This parameter identifies a pin factory within the target filter. If the filter contains n pin factories, valid pin IDs range from 0 to n-1.
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
A DirectKS application program typically does not use this constructor. Instead, it indirectly creates a CKsAudRenPin object for a rendering pin by calling CKsAudFilter::EnumeratePins.
See Also
CKsAudFilter, CKsAudFilter::EnumeratePins
The CKsFilter class encapsulates a KS filter. CKsFilter is derived from base class CKsIrpTarget. Class CKsAudFilter is derived from CKsFilter.
This class is defined in header file filter.h in the sample directory.
A CKsFilter object serves as a user-mode proxy for a KS filter object. CKsFilter and derived objects are created by the CKsEnumFilters::EnumFilters function. This function stores the KS filter's device-interface path name into the m_szFilterName member, which is a character buffer. This path name can be passed to Win32 functions such as CreateFile. For the sake of simplicity, the size of the character buffer is declared to be MAX_PATH, which is inefficient in terms of memory use. A production application might allocate this buffer more efficiently.
Most of the members of CKsFilter are lists of pointers to pins, and they might not all be necessary for a production application. For example, if an application only needs to render PCM audio data to a single pin, then all these lists could be eliminated in favor of a single pointer to a list of render pins. A CKsFilter object contains the following (protected) pin lists:
TList<CKsPin> m_listPins;
TList<CKsPin> m_listRenderSinkPins;
TList<CKsPin> m_listRenderSourcePins;
TList<CKsPin> m_listCaptureSinkPins;
TList<CKsPin> m_listCaptureSourcePins;
TList<CKsPin> m_listNoCommPins;
The following table describes these members.
Member Name |
Description |
m_listPins |
Master list of pins. |
m_listRenderSinkPins |
Subset of pins in m_listPins that are render-sink pins. These pins process input streams to the filter containing rendering data. |
m_listRenderSourcePins |
Subset of pins in m_listPins that are render-source pins. These pins process output streams from the filter containing rendering data. |
m_listCaptureSinkPins |
Subset of pins in m_listPins that are capture-sink pins. These pins process input streams to the filter containing capture data. |
m_listCaptureSourcePins |
Subset of pins in m_listPins that are capture-source pins. These pins process output streams from the filter containing captured data. |
m_listNoCommPins |
Subset of pins in m_listPins that are bridge pins, which do not support IRP communication. |
For example, a sink-render pin appears in both the m_listPins and m_listRenderSinkPins lists, which both point to a shared CKsPin object.
In addition to the members inherited from base class CKsIrpTarget, CKsFilter contains the following public members:
CKsFilter::GetPinPropertyMulti
CKsFilter::GetPinPropertySimple
These members are described in the following sections.
The CKsFilter constructor creates and initializes an object of type CKsFilter.
CKsFilter (
IN LPCTSTR pszName,
OUT HRESULT *phr
);
Parameters
pszName
Pointer to a NULL-terminated character string that contains the KS filter's device-interface path name. This path name can be passed to Win32 functions such as CreateFile. For more information, see the description of the SP_DEVICE_INTERFACE_DETAIL_DATA structure in the Windows DDK documentation.
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function writes S_OK. Otherwise, it writes an appropriate error code.
Comments
A DirectKS application program typically does not use this constructor. Instead, it indirectly creates CKsAudCapFilter and CKsAudRenFilter objects for a list of capture or rendering filters by calling CKsEnumFilters::EnumFilters.
See Also
The EnumerateNodes member function enumerates the topology nodes in the filter.
virtual HRESULT
EnumerateNodes (
void
);
Parameters
None
Return Value
EnumerateNodes returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
This method enumerates nodes on the filter and adds them to the list in the m_listNodes member. By default, the CKsEnumFilters::EnumFilters function calls EnumerateNodes for each filter that it enumerates. Note that an application might have no use for topology nodes, in which case the sample code can be simplified by removing all functionality related to nodes.
Each time this function is called, it deletes any previously created list of nodes for the filter before generating the new list of nodes.
See
Also
The EnumeratePins member function enumerates the pins in the filter.
virtual HRESULT
EnumeratePins (
void
);
Parameters
None
Return Value
EnumeratePins returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
This function creates an internal list of the pin factories in the filter. For each pin factory, the function creates an object of type CKsAudRenPin, CKsAudCapPin, or CKsAudPin, depending on the pin type: rendering pin (KSPIN_COMMUNICATION_SINK), capture pin (KSPIN_COMMUNICATION_SOURCE), or bridge pin (KSPIN_COMMUNICATION_NONE). The CKsFilter object maintains a list of each pin type as part of its internal state.
Call this function before calling a function such as CKsAudRenFilter::CreateRenderPin that creates a pin.
See
Also
CKsAudRenPin, CKsAudCapPin, CKsAudPin, CKsAudRenFilter::CreateRenderPin
The GetPinPropertyMulti member function gets the values for a multi-valued property request.
HRESULT
GetPinPropertyMulti (
IN ULONG
nPinID,
IN REFGUID guidPropertySet,
IN ULONG
nProperty,
OUT PKSMULTIPLE_ITEM *ppKsMultipleItem
);
Parameters
nPinID
Specifies the pin ID. Each pin factory in a filter is identified by its pin ID, which is an index into the filter's pin descriptor array. For more information on pin IDs, see the Windows DDK documentation.
guidPropertySet
Reference to the GUID that identifies the property set. For more information, see the KSPROPSETID_XXX GUIDs that are listed in the Windows DDK documentation.
nProperty
Specifies the property item. If the property set contains n items, the items are numbered 0 through n-1. For more information, see the Windows DDK documentation for the list of KSPROPERTY_XXX enumeration values that are defined for each property set.
ppKsMultipleItem
Pointer to a location into which the function writes a pointer to a buffer containing the output data from the property handler. This buffer begins with a PKSMULTIPLE_ITEM structure, which serves as a header for the array of property values that follow it in the buffer. For more information, see the description of PKSMULTIPLE_ITEM in the Windows DDK documentation.
Return Value
GetPinPropertyMulti returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
The function uses the C++ new[] operator to allocate the buffer that it outputs through the ppKsMultipleItem parameter. The caller is responsible for deleting the buffer when it is no longer needed. The function allocates the buffer as a BYTE array, and the caller should delete it as follows:
delete[] (BYTE *)pKsMultipleItem;
This example
assumes that the caller passed the value &pKsMultipleItem to GetPinPropertyMulti as the fourth argument.
The GetPinPropertySimple member function gets the value for a simple property request.
HRESULT
GetPinPropertySimple (
IN ULONG
nPinID,
IN REFGUID guidPropertySet,
IN ULONG
nProperty,
OUT PVOID
pvValue,
OUT ULONG
cbValue
);
Parameters
nPinID
Specifies the pin ID. Each pin factory in a filter is identified by its pin ID, which is an index into the filter's pin descriptor array. For more information on pin IDs, see the Windows DDK documentation.
guidPropertySet
Reference to the GUID that identifies the property set. For more information, see the KSPROPSETID_XXX GUIDs that are listed in the Windows DDK documentation.
nProperty
Specifies the property item. If the property set contains n items, the items are numbered 0 through n-1. For more information, see the Windows DDK documentation for the list of KSPROPERTY_XXX enumeration values that are defined for each property set.
pvValue
Pointer to a caller-allocated buffer into which the function writes the property call's output value.
cbValue
Specifies the size in bytes of the buffer that pvValue points to.
Return Value
GetPinPropertySimple returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
The Instantiate member function instantiates the KS filter.
virtual HRESULT
Instantiate (
void
);
Parameters
None
Return Value
Instantiate returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
This function instantiates the KS filter object represented by CKsFilter. If the function call succeeds, then the CKsFilter object's m_handle member becomes valid. Call Instantiate before calling any of the CKsFilter or CKsIrpTarget member functions that require m_handle to be valid (this is the majority of functions). CKsEnumFilters::EnumFilters implicitly calls Instantiate if it is called with fInstantiate = TRUE (the default).
See
Also
The CKsIrpTarget class encapsulates a kernel-resident IRP target such as a KS filter or KS pin. Classes CKsFilter and CKsPin are derived from CKsIrpTarget.
This class is defined in header file irptgt.h in the sample directory.
This class abstracts the features that are common to both KS filters and KS pins. These filters and pins are kernel objects and can be the target of MJ_DEVICECONTROL IRPs (IOCTL requests). The CKsIrpTarget class implements the IOCTL calling conventions, which are the same for filter objects and pin objects.
CKsIrpTarget contains the following public members:
These members are described in the following sections.
The CKsIrpTarget constructor creates and initializes an object of type CKsIrpTarget.
CKsIrpTarget (
IN HANDLE
handle
);
Parameters
handle
Specifies a handle that was created by the operating system. A handle value of NULL or INVALID_HANDLE_VALUE is invalid.
Comments
A DirectKS application program typically does not use this constructor. Instead, it can indirectly create user-mode proxy objects for KS filters and KS pins by calling the following functions:
CKsAudCapFilter::CreateCapturePin
CKsAudRenFilter::CreateRenderPin
See Also
CKsAudCapFilter::CreateCapturePin, CKsAudRenFilter::CreateRenderPin, CKsEnumFilters::EnumFilters
The Close member function closes the kernel object representing the IRP target (filter or pin instance).
BOOL
Close (
void
);
Parameters
None
Return Value
Close returns a nonzero value if it succeeds. Otherwise, it returns zero.
Comments
This function closes either a filter instance that was created by a CKsFilter::Instantiate call or a pin instance that was created by a CKsPin::Instantiate call.
This function closes the CKsIrpTarget object's underlying kernel-object handle, thereby deleting the kernel object. No other member functions should be called on the CKsIrpTarget object after Close has been called.
See
Also
CKsFilter::Instantiate, CKsPin::Instantiate
The GetHandle member function gets the handle to the kernel object that represents the IRP target (KS filter or KS pin).
HANDLE
GetHandle (
void
);
Parameters
None
Return Value
GetHandle returns the IRP target's handle.
Comments
The caller should not attempt to close this handle directly by calling CloseHandle. To close the handle, call CKsIrpTarget::Close instead. For more information, see the description of the CloseHandle system call in the Platform SDK documentation.
This function returns the handle of the underlying kernel object. This handle can be used in calls to DeviceIoControl, WaitForSingleObject, and other handle-based Win32 functions. However, the DirectKS functions should provide enough functionality that this handle should rarely be needed directly.
See Also
The IsValidHandle member function indicates whether the specified handle is valid.
static BOOL
IsValidHandle (
HANDLE handle
);
Parameters
handle
Specifies a handle that was created by the operating system.
Return Value
IsValidHandle returns TRUE if the handle is valid. Otherwise, it returns FALSE.
Comments
A handle value of NULL or INVALID_HANDLE_VALUE is invalid.
The SafeCloseHandle member function closes a handle.
static BOOL
SafeCloseHandle (
HANDLE& handle
);
Parameters
handle
Specifies a handle that was created by the operating system.
Return Value
SafeCloseHandle returns TRUE if the function either succeeded in closing the handle or the handle is invalid. The function returns FALSE if it fails in an attempt to close an apparently valid handle.
Comments
A handle value of NULL or INVALID_HANDLE_VALUE is invalid.
In order to avoid generating an exception, this function does not try to close an obviously invalid handle value.
The SyncIoctl member function sends a synchronous IOCTL request to an IRP target specified by a handle.
static HRESULT
SyncIoctl (
IN HANDLE
handle,
IN ULONG
ulIoctl,
IN PVOID
pvInBuffer,
IN ULONG
cbInBuffer,
OUT PVOID
pvOutBuffer,
OUT ULONG
cbOutBuffer,
OUT PULONG
pulBytesReturned
);
Parameters
handle
Specifies a handle that was created by the operating system. A handle value of NULL or INVALID_HANDLE_VALUE is invalid.
ulIoctl
Specifies the control code for the operation. This value identifies the specific operation to be performed and the type of device on which to perform it. For example, ulIoctl=IOCTL_KS_PROPERTY specifies a KS property request.
pvInBuffer
Pointer to a caller-allocated buffer containing the input data for the operation. This data specifies what operation to perform and how to perform the operation. For example, KS clients use the KSP_PIN structure to specify the property and pin type within a KSPROPSETID_Pin property request. This parameter can be NULL if the ulIoctl parameter specifies an operation that does not require input data. For information about KSP_PIN and KSPROPSETID_Pin, see the Windows DDK documentation.
cbInBuffer
Specifies the size, in bytes, of the buffer pointed to by pvInBuffer.
pvOutBuffer
Pointer to a caller-allocated buffer into which the function writes the operation's output data.
cbOutBuffer
Specifies the size, in bytes, of the buffer pointed to by pvOutBuffer.
pulBytesReturned
Pointer to a caller-allocated variable into which the function writes the number of bytes of data returned in the buffer pointed to by pvOutBuffer.
Return Value
SyncIoctl returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
For some IOCTL operations, the caller might not know in advance how large the buffer pointed to by pvOutBuffer should be. For example, in the case of a KS property basic-support request, property handlers follow a set of conventions that allow callers to easily determine how large to make the output buffer that contains the KSPROPERTY_DESCRIPTOR structure. For more information, see the Windows DDK documentation.
The CKsPin class encapsulates a KS pin. CKsPin is derived from base class CKsIrpTarget. Classes CKsAudCapPin and CKsAudRenPin are derived from CKsPin.
This class is defined in header file pin.h in the sample directory.
In addition to the members inherited from base class CKsIrpTarget, CKsPin contains the following public members:
CKsPin::HasDataRangeWithSpecifier
These members are described in the following sections.
The CKsPin constructor creates and initializes an object of type CKsPin.
CKsPin (
IN CKsFilter *pFilter,
IN ULONG
nId,
OUT HRESULT *phr
);
Parameters
pFilter
Pointer to the CKsFilter object representing the filter that the new pin is attached to.
nId
Specifies the pin ID. This parameter identifies a pin factory within the target filter. If the filter contains n pin factories, valid pin IDs range from 0 to n-1.
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
A DirectKS application program typically does not use this constructor. Instead, it indirectly creates a CKsAudCapPin or CKsAudRenPin object for a capture or rendering pin by calling CKsAudFilter::EnumeratePins.
See Also
CKsFilter, CKsAudFilter::EnumeratePins
The ClosePin member function closes the pin.
void
ClosePin (
void
);
Parameters
None
Return Value
None
Comments
If the pin was previously opened by a call to CKsPin::Instantiate, the ClosePin function closes the pin (by closing the pin handle). If the pin is not open, the ClosePin function has no effect.
See
Also
The GetCommunication member function gets information about the type of communication that the pin uses.
HRESULT
GetCommunication (
KSPIN_COMMUNICATION *pCommunication
);
Parameters
pCommunication
Pointer to a caller-allocated variable into which the function writes a parameter indicating the pin's communication type. The function sets the variable to one of the following parameter values:
KSPIN_COMMUNICATION_NONE
KSPIN_COMMUNICATION_SINK
KSPIN_COMMUNICATION_SOURCE
KSPIN_COMMUNICATION_BOTH
KSPIN_COMMUNICATION_BRIDGE
For the meaning of these parameter values, see the description of the KSPROPERTY_PIN_COMMUNICATION property in the Windows DDK documentation.
Return Value
GetCommunication returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
The GetDataFlow member function gets the direction of the data that flows through the pin.
HRESULT
GetDataFlow (
KSPIN_DATAFLOW *pDataFlow
);
Parameters
pDataFlow
Pointer to a caller-allocated variable into which the function writes a parameter indicating the pin's data-flow direction. The function sets the variable to one of the following parameter values:
KSPIN_DATAFLOW_IN
KSPIN_DATAFLOW_OUT
For the meaning of these parameter values, see the description of the KSPROPERTY_PIN_DATAFLOW property in the Windows DDK documentation.
Return Value
GetDataFlow returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
The GetId member function gets the pin ID.
ULONG
GetId (
void
);
Parameters
None
Return Value
GetId returns a pin ID that identifies the pin factory within the filter. If the filter contains n pin factories, valid pin IDs range from 0 to n-1.
The GetPinDescriptor member function gets a description of the pin.
PPIN_DESCRIPTOR
GetPinDescriptor (
void
);
Parameters
None
Return Value
GetPinDescriptor returns a pointer to a PIN_DESCRIPTOR structure that describes the pin.
Comments
The caller should not attempt to modify or delete the PIN_DESCRIPTOR structure pointed to by the function's return value.
See
Also
The GetState member function gets the current state of the wave stream that is associated with the pin.
HRESULT
GetState (
OUT PKSSTATE pksState
);
Parameters
pksState
Pointer to a caller-allocated variable into which the function outputs the pin's current state. The state is specified by one of the following KSSTATE enumeration values:
KSSTATE_STOP
KSSTATE_ACQUIRE
KSSTATE_PAUSE
KSSTATE_RUN
For the meaning of these values, see the description of KSSTATE in the Windows DDK documentation.
Return Value
GetState returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
The GetType member function gets the pin type.
ETechnology
GetType (
void
);
Parameters
None
Return Value
GetType returns an ETechnology enumeration value that specifies the pin type. ETechnology is defined in sample header file kssample.h. The function returns one of the values shown in the following table.
Return Value |
Pin Type |
eUnknown |
Unknown pin type |
eAudRen |
Audio rendering pin |
eAudCap |
Audio capture |
The HasDataRangeWithSpecifier member function determines whether the pin supports the specified data-format specifier.
BOOL
HasDataRangeWithSpecifier (
REFGUID guidFormatSpecifier
);
Parameters
guidFormatSpecifier
Reference to a data-format specifier GUID. The function compares this GUID to the specifier GUID in each of the data ranges contained in the pin's descriptor.
Return Value
HasDataRangeWithSpecifier returns TRUE if it finds a data range that supports the data-format specifier. Otherwise, it returns FALSE.
Comments
The CKsPin object contains a pin descriptor, which is a structure of type PIN_DESCRIPTOR that contains an array of the pin's supported data ranges. The function searches the array for a data range with a matching specifier. For more information, see the description of the KSDATARANGE structure's Specifier member in the Windows DDK documentation.
See Also
The Instantiate member function creates a KS pin instance.
virtual HRESULT
Instantiate (
IN BOOL
fLooped = FALSE
);
Parameters
fLooped
Specifies whether the pin's buffer is looped. If TRUE, the buffer is looped. If FALSE, the buffer is not looped. If the pin provides looped buffering, then when the pin's buffer pointer reaches the end of the buffer, it automatically wraps to the start of the buffer. In the case of a nonlooped buffer, the pin processes a buffer only once and is finished with the buffer when it reaches the buffer's end. If not specified, the default value of fLooped is FALSE.
Return Value
Instantiate returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
This function creates an instance of the KS pin. Note that creating the CKsPin object does not necessarily create the underlying KS pin instance.
To close a pin instance that is created by this function, call CKsPin::ClosePin.
See Also
The ReadData member function reads a block of data from a source pin.
HRESULT
ReadData (
IN KSSTREAM_HEADER *pKSSTREAM_HEADER,
IN OVERLAPPED *pOVERLAPPED
);
Parameters
pKSSTREAM_HEADER
Pointer to a caller-allocated buffer containing a KSSTREAM_HEADER structure. Before calling the function, the caller should initialize the structure's Size, FrameExtent, Data, and DataUsed members. Set Size to the size in bytes of the KSSTREAM_HEADER structure that pKSSTREAM_HEADER points to. This size should be at least sizeof(KSSTREAM_HEADER). Set FrameExtent to the size in bytes of the frame (physically contiguous buffer), and set Data to point to the frame. Set DataUsed to zero; the function overwrites this value with the number of bytes actually used.
pOVERLAPPED
Pointer to an OVERLAPPED structure specifying how to do an asynchronous read operation. See the following Comments section.
Return Value
ReadData returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
If the pin instance was opened with the FILE_FLAG_OVERLAPPED flag, pOVERLAPPED must point to a valid OVERLAPPED structure. In this case, the read operation is performed as an overlapped (asynchronous) operation. If the device was opened with FILE_FLAG_OVERLAPPED and pOVERLAPPED is NULL, the function fails in unpredictable ways.
If the pin instance was opened without specifying the FILE_FLAG_OVERLAPPED flag, pOVERLAPPED is ignored and the function does not return until the operation has either been completed or an error occurs.
For more information, see the description of OVERLAPPED in the Windows DDK documentation.
See Also
The Reset member function resets the pin to the state that it was in at acquire time.
HRESULT
Reset (
void
);
Parameters
None
Return Value
Reset returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
For more information, see the description of IOCTL_KS_RESET_STATE in the Windows DDK documentation.
The SetFormat member function sets the pin's data format.
HRESULT
SetFormat (
KSDATAFORMAT *pFormat
);
Parameters
pFormat
Pointer to a KSDATAFORMAT structure specifying the new wave format for the stream that the pin processes. For more information, see the description of KSDATAFORMAT in the Windows DDK documentation.
Return Value
SetFormat returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
Call this function to specify the stream format for a pin before calling CKsPin::Instantiate to instantiate the pin.
SetFormat has no effect on a pin that has already been instantiated.
The pFormat parameter typically points to a KSDATAFORMAT_WAVEFORMATEX structure that specifies the wave format for the stream. The first member of this structure is an embedded structure of type KSDATAFORMAT, which is followed by a member of type WAVEFORMATEX or WAVEFORMATEXTENSIBLE. For more information on these structures, see the Windows DDK documentation.
See
Also
The SetPinConnect member function sets the pin's connection.
HRESULT
SetPinConnect (
PKSPIN_CONNECT pksPinConnect,
ULONG cbKsPinConnect
);
Parameters
pksPinConnect
Pointer to a KSPIN_CONNECT structure that specifies the type of connection that the caller is requesting for the pin. For more information, see the description of KSPIN_CONNECT in the Windows DDK documentation.
cbKsPinConnect
The size in bytes of the buffer pointed to by the pksPinConnect parameter.
Return Value
SetPinConnect returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
This function sets the pin-connection data that the CKsPin::Instantiate function subsequently uses when it creates a pin instance. This data is part of the CKsPin object's internal state. An application calls this function to override the default values that the constructor assigns to the pin-connection data when the object is created.
See
Also
The SetState member function sets the state of the wave stream that is associated with the pin.
virtual HRESULT
SetState (
IN KSSTATE ksState
);
Parameters
ksState
Specifies the pin's new state. The state is specified by one of the following KSSTATE enumeration values:
KSSTATE_STOP
KSSTATE_ACQUIRE
KSSTATE_PAUSE
KSSTATE_RUN
For the meaning of these values, see the description of KSSTATE in the Windows DDK documentation.
Return Value
SetState returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
An application calls this function to start, stop, and pause the audio stream.
The WriteData member function writes a block of data to a sink pin.
HRESULT
WriteData(
IN KSSTREAM_HEADER *pKSSTREAM_HEADER,
IN OVERLAPPED *pOVERLAPPED
);
Parameters
pKSSTREAM_HEADER
Pointer to a caller-allocated buffer containing a KSSTREAM_HEADER structure. Before calling the function, the caller should fill in this structure. One of the values that the caller writes to this structure is a pointer to the data being written to the pin. For information about KSSTREAM_HEADER, see the Windows DDK documentation.
pOVERLAPPED
Pointer to an OVERLAPPED structure specifying how to do an asynchronous read operation. See the following Comments section.
Return Value
WriteData returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
If the pin instance was opened with the FILE_FLAG_OVERLAPPED flag, pOVERLAPPED must point to a valid OVERLAPPED structure. In this case, the write operation is performed as an overlapped (asynchronous) operation. If the device was opened with FILE_FLAG_OVERLAPPED and pOVERLAPPED is NULL, the function fails in unpredictable ways.
If the pin instance was opened without specifying the FILE_FLAG_OVERLAPPED flag, pOVERLAPPED is ignored and the function does not return until the operation has either been completed or an error occurs.
For more information, see the description of OVERLAPPED in the Windows DDK documentation.
See Also
The DirectKS sample code implements the following utility classes:
These classes are described in the following sections.
The CKsEnumFilters class encapsulates a list of enumerated KS filters.
This class is defined in header file enum.h in the sample directory.
This class provides the starting point for a DirectKS application program. The EnumFilters member function enumerates the KS filters in the system satisfying a set of criteria that the application specifies. The function maintains a list of the enumerated filters in its m_listFilters member. If the EnumFilters parameters adequately describe the filters needed by the application, it should be able to simply use the first filter in the list. Otherwise, the application can traverse the list to query the individual filters in the list for their properties, and it can refine the contents of the list by removing selected filters from the list.
CKsEnumFilters contains the following public members:
CKsEnumFilters::CKsEnumFilters
These members are described in the following sections.
The CKsEnumFilters constructor creates and initializes an object of type CKsEnumFilters.
CKsEnumFilters (
OUT HRESULT *phr
);
Parameters
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function writes S_OK. Otherwise, it writes an appropriate error code.
The DestroyLists member function destroys the CKsEnumFilters object's list of enumerated filters.
virtual HRESULT
DestroyLists (
void
);
Parameters
None
Return Value
DestroyLists returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
The CKsEnumFilters::EnumFilters function destroys any existing list of enumerated filters before generating a new list. Calling DestroyLists before calling EnumFilters is harmless, but unnecessary.
See
Also
The EnumFilters
member function enumerates a list of KS filters that meet the specified
requirements.
HRESULT
EnumFilters (
IN ETechnology eFilterType,
IN GUID
*aguidCategories,
IN ULONG
cguidCategories,
IN BOOL
fNeedPins,
IN BOOL
fNeedNodes,
IN BOOL
fNeedConnections,
IN BOOL
fInstantiate
);
Parameters
eFilterType
Specifies the filter type. Set this member to one of the ETechnology enumeration values shown in the following table.
Value |
Filter Type |
eAudRen |
Audio rendering filter |
eAudCap |
Audio capture filter |
ETechnology is defined in sample header file kssample.h.
aguidCategories
Pointer to an array of KSCATEGORY_XXX GUIDs specifying the categories to which the enumerated filters belong. For example, all audio filters belong to KSCATEGORY_AUDIO. In addition, a filter that captures or renders audio data also belongs to the KSCATEGORY_CAPTURE or KSCATEGORY_RENDER category.
cguidCategories
Specifies the number of elements in the array that aguidCategories points to.
fNeedPins
Specifies whether to create a list of pin factories for each enumerated filter. This list is part of the filter-proxy object's internal state. If TRUE, the function creates the pin list. If FALSE, it does not create the list.
fNeedNodes
Specifies whether to create a list of topology nodes for each enumerated filter. This list is part of the filter-proxy object's internal state. If TRUE, the function creates the node list. If FALSE, it does not create the list.
fNeedConnections
Specifies whether to create a list of internal connections for each enumerated filter. This list is part of the filter-proxy object's internal state. If TRUE, the function creates the connection list. If FALSE, it does not create the list.
fInstantiate
Specifies whether to instantiate each enumerated filter. If TRUE, the function instantiates each filter that it adds to its list of enumerated filters. If FALSE, it does not instantiate the filters.
Return Value
EnumFilters returns a status code indicating whether the function call succeeded. If successful, the function returns S_OK. Otherwise, it returns an appropriate error code.
Comments
Before enumerating the new list of filters, the function deletes any previous list of filters that might have been created.
The m_listFilters member is a list of enumerated filters.
TList<CKsFilter> m_listFilters;
Comments
Each item in the list contains a pointer to a CKsFilter object. The CKsEnumFilters::EnumFilters function generates this list.
In order to use one of the filter-proxy objects in the list, either remove the CKsFilter object from the list, or create a duplicate CKsFilter object and use that.
See Also
TList, CKsFilter, CKsEnumFilters::EnumFilters
The CKsNode class encapsulates a topology node inside a KS filter.
This class is defined in header file node.h in the sample directory.
CKsNode contains the following public members:
These members are described in the following sections.
The CKsNode constructor creates and initializes an object of type CKsNode.
CKsNode (
ULONG nID,
REFGUID guidType,
HRESULT *phr
);
CKsNode (
CKsNode *pksnCopy,
HRESULT *phr
);
Parameters
nID
Specifies the node ID. This parameter identifies a node within the target filter. If the filter contains an array of n node descriptors, valid node IDs range from 0 to n-1.
guidType
Specifies the KS node type. For example, a volume-control node is identified by the GUID value KSNODETYPE_VOLUME. For a list of KS node-type GUIDs, see the Windows DDK documentation.
phr
Pointer to a caller-allocated variable into which the function writes a status code indicating whether the function call succeeded. If successful, the function writes S_OK. Otherwise, it writes an appropriate error code.
pksnCopy
Pointer to a CKsNode object that is to be copied. The copy contains the same node ID and node-type GUID as the original object.
The GetCpuResources member function gets information about the CPU resources that the node uses.
ULONG
GetCpuResources (
void
);
Parameters
None
Return Value
GetCpuResources returns a ULONG value that indicates whether the node's functionality is implemented in hardware or is emulated in software that runs on the system CPU. The function returns one of the values shown in the following table.
Return Value |
Meaning |
KSAUDIO_CPU_RESOURCES_UNINITIALIZED |
The node's resources are not initialized. |
KSAUDIO_CPU_RESOURCES_HOST_CPU |
The node implements its functionality in software that runs on the host CPU. |
KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU |
The node implements its functionality in hardware. |
Comments
For more information, see the description of the KSPROPERTY_AUDIO_CPU_RESOURCES property in the Windows DDK documentation.
The GetId member function returns the node ID.
ULONG
GetId (
void
);
Parameters
None
Return Value
GetId returns the node ID. This value identifies a node within the target filter. If the filter contains an array of n node descriptors, valid node IDs range from 0 to n-1.
The GetType member function gets the node type.
GUID
GetType (
void
);
Parameters
None
Return Value
GetType returns a GUID value that indicates the node type. For example, a volume node is identified by the GUID value KSNODETYPE_VOLUME. For a list of KS node-type GUIDs, see the Windows DDK documentation.
The TList class template defines a generic set of functions for operating on a doubly linked list of objects.
The TList class template defines the following member functions:
AddHead
AddTail
Find
GetAt
GetCount
GetHead
GetHeadPosition
GetNext
Initialize
InsertBefore
IsEmpty
RemoveAll
RemoveAt
RemoveHead
RemoveTail
See the definitions of these functions in header file tlist.h in the sample directory.
You can use these functions to traverse the lists that are exposed by the following public members:
The DirectKS sample code defines the following structure:
This structure is defined in the following section.
The PIN_DESCRIPTOR structure contains information about a KS pin’s interfaces, mediums, and data ranges.
typedef struct
{
ULONG cInterfaces;
PKSIDENTIFIER pInterfaces;
ULONG cMediums;
PKSIDENTIFIER pMediums;
ULONG cDataRanges;
PKSDATARANGE pDataRanges;
ULONG cConstrDataRanges;
PKSDATARANGE pConstrDataRanges;
KSPIN_DATAFLOW DataFlow;
KSPIN_COMMUNICATION Communication;
KSPIN_CINSTANCES CInstances;
KSPIN_CINSTANCES CInstancesGlobal;
KSPIN_CINSTANCES CInstancesNecessary;
PKSPIN_PHYSICALCONNECTION PhysicalConnection;
GUID Category;
PWCHAR Name;
PKSMULTIPLE_ITEM pmiDataRanges;
PKSMULTIPLE_ITEM pmiMediums;
PKSMULTIPLE_ITEM pmiInterfaces;
} PIN_DESCRIPTOR,
*PPIN_DESCRIPTOR;
Members
cInterfaces
Specifies the number of entries in the array pointed to by pInterfaces.
pInterfaces
Specifies the KS interfaces supported by this pin type. This member points to an array of KSIDENTIFIER structures. For more information, see the description of KSPROPERTY_PIN_INTERFACES in the Windows DDK documentation.
cMediums
Specifies the number of entries in the array pointed to by pMediums.
pMediums
Specifies the KS mediums supported by this pin type. This member points to an array of KSIDENTIFIER structures. For more information, see the description of KSPROPERTY_PIN_MEDIUMS in the Windows DDK documentation.
cDataRanges
Specifies the number of entries in the array pointed to by pDataRanges.
pDataRanges
Specifies the data ranges supported by this pin type. This member points to an array of KSDATARANGE structures that specify the ranges of data formats that the pin can handle. For more information, see the description of KSDATARANGE in the Windows DDK documentation.
cConstrDataRanges
Not currently used.
pConstrDataRanges
Not currently used.
DataFlow
Specifies the pin's data-flow direction. This member is set to one of the values shown in the following table.
Value |
Meaning |
KSPIN_DATAFLOW_IN |
Data flows into the filter through the pin (sink). |
KSPIN_DATAFLOW_OUT |
Data flows out of the filter through the pin (source). |
For more information, see the description of the KSPIN_DATAFLOW_XXX values in the Windows DDK documentation.
Communication
Specifies the pin's communication type. This member can be one of the following parameter values:
KSPIN_COMMUNICATION_NONE
KSPIN_COMMUNICATION_SINK
KSPIN_COMMUNICATION_SOURCE
KSPIN_COMMUNICATION_BOTH
KSPIN_COMMUNICATION_BRIDGE
For the meaning of these parameter values, see the description of the KSPROPERTY_PIN_COMMUNICATION property in the Windows DDK documentation.
CInstances
Specifies the maximum number of times that the pin can be instantiated on a single instance of the filter. The count can be set to zero to indicate that the pin cannot be instantiated. A value of ULONG(-1) indicates the pin can be instantiated any number of times. Any other value indicates the specific number of times that the pin can be instantiated.
CInstancesGlobal
Specifies the global maximum number of times that this pin type can be instantiated. The global maximum counts the number of pin instances that the adapter driver can support across all instances of the filter. The count can be set to zero to indicate that the pin cannot be instantiated. A value of ULONG(-1) indicates the pin can be instantiated any number of times. Any other value indicates the specific number of times that the pin can be instantiated.
CInstancesNecessary
Specifies the minimum number of times that the pin needs to be instantiated on an instance of the filter. This member is a definite lower bound on the number of instances of the pin that must exist in order for the filter to function.
PhysicalConnection
Pointer to a KSPIN_PHYSICALCONNECTION structure specifying the pin's physical connection to a pin on another filter. For more information, see the description of KSPIN_PHYSICALCONNECTION in the Windows DDK documentation.
Category
Specifies the pin's category GUID.
Name
Pointer to the localized Unicode string name for the pin type. The name is stored as a null-terminated string in a WCHAR array. This member can be specified as NULL if the Category member uniquely identifies the pin factory within the filter. If two or more pins share the same Category GUID, the Name member is used in conjunction with the Category GUID to uniquely identify each of the pins.
pmiDataRanges
Pointer to a buffer containing a KSMULTIPLE_ITEM structure that is followed by an array of KS data ranges. The data is in the same format as the output data for a KSPROPERTY_PIN_DATARANGES property request. For more information, see the description of KSPROPERTY_PIN_DATARANGES in the Windows DDK documentation.
pmiMediums
Pointer to a buffer containing a KSMULTIPLE_ITEM structure that is followed by an array of KS mediums. The data is in the same format as the output data for a KSPROPERTY_PIN_MEDIUMS property request. For more information, see the description of KSPROPERTY_PIN_MEDIUMS in the Windows DDK documentation.
pmiInterfaces
Pointer to a buffer containing a KSMULTIPLE_ITEM structure that is followed by an array of KS interfaces. The data is in the same format as the output data for a KSPROPERTY_PIN_INTERFACES property request. For more information, see the description of KSPROPERTY_PIN_INTERFACES in the Windows DDK documentation.
Comments
The pDataRanges member points to the array of KS data ranges in the buffer pointed to by the pmiDataRanges members. Although pDataRanges is redundant, it does provide more direct access to the data-range array than pmiDataRanges does. Similarly, the pMediums member points to the array of KS mediums in the buffer pointed to by the pmiMediums member, and the pInterfaces member points to the array of KS interfaces in the buffer pointed to by the pmiMediums member.
The CKsPin::GetPinDescriptor function returns a pointer to a PIN_DESCRIPTOR structure.
This structure is defined in header file pin.h in the sample directory.
See Also