// returns format id in style of WAVEFORMATEX wFormatTag, if it possible
bool FormatDetect(const WAVEFORMATEX* format, WORD* id)
{
	if (format->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
	{
		const WAVEFORMATEXTENSIBLE *ext = (const WAVEFORMATEXTENSIBLE*)format;
		if (IS_VALID_WAVEFORMATEX_GUID(&ext->SubFormat))
		{
			*id = EXTRACT_WAVEFORMATEX_ID(&ext->SubFormat);
			return true;
		}
		return false;
	}
	*id = format->wFormatTag;
	return true;
}
/* return the maximum channel count supported by any pin on the device. 
   if isInput is non-zero we query input pins, otherwise output pins.
*/
int PaWin_WDMKS_QueryFilterMaximumChannelCount( void *wcharDevicePath, int isInput )
{
    HANDLE deviceHandle;
    int pinCount, pinId, i;
    int result = 0;
    KSPIN_DATAFLOW requiredDataflowDirection = (isInput ? KSPIN_DATAFLOW_OUT : KSPIN_DATAFLOW_IN );
    
    if( !wcharDevicePath )
        return 0;

    deviceHandle = CreateFileW( (LPCWSTR)wcharDevicePath, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
    if( deviceHandle == INVALID_HANDLE_VALUE )
        return 0;

    pinCount = GetKSFilterPinCount( deviceHandle );
    for( pinId = 0; pinId < pinCount; ++pinId )
    {
        KSPIN_COMMUNICATION communication = GetKSFilterPinPropertyCommunication( deviceHandle, pinId );
        KSPIN_DATAFLOW dataflow = GetKSFilterPinPropertyDataflow( deviceHandle, pinId );
        if( ( dataflow == requiredDataflowDirection ) &&
                (( communication == KSPIN_COMMUNICATION_SINK) ||
                 ( communication == KSPIN_COMMUNICATION_BOTH)) 
             && ( KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, 
                    KSPROPERTY_PIN_INTERFACES, &KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_STREAMING )
                || KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, 
                    KSPROPERTY_PIN_INTERFACES, &KSINTERFACESETID_Standard, KSINTERFACE_STANDARD_LOOPED_STREAMING ) )
             && KSFilterPinPropertyIdentifiersInclude( deviceHandle, pinId, 
                    KSPROPERTY_PIN_MEDIUMS, &KSMEDIUMSETID_Standard, KSMEDIUM_STANDARD_DEVIO ) )
         {
            KSMULTIPLE_ITEM* item = NULL;
            if( WdmGetPinPropertyMulti( deviceHandle, pinId, KSPROPERTY_PIN_DATARANGES, &item ) == paNoError )
            {
                KSDATARANGE *dataRange = (KSDATARANGE*)(item+1);

                for( i=0; i < item->Count; ++i ){

                    if( IS_VALID_WAVEFORMATEX_GUID(&dataRange->SubFormat)
                            || memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID) ) == 0
                            || memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID) ) == 0
                            || ( ( memcmp( (void*)&dataRange->MajorFormat, (void*)&KSDATAFORMAT_TYPE_AUDIO, sizeof(GUID) ) == 0 )
                                && ( memcmp( (void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_WILDCARD, sizeof(GUID) ) == 0 ) ) )
                    {
                        KSDATARANGE_AUDIO *dataRangeAudio = (KSDATARANGE_AUDIO*)dataRange;
                        
                        /*
                        printf( ">>> %d %d %d %d %S\n", isInput, dataflow, communication, dataRangeAudio->MaximumChannels, devicePath );
                       
                        if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, sizeof(GUID) ) == 0 )
                            printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_WAVEFORMATEX\n" );
                        else if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_DSOUND, sizeof(GUID) ) == 0 )
                            printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_DSOUND\n" );
                        else if( memcmp((void*)&dataRange->Specifier, (void*)&KSDATAFORMAT_SPECIFIER_WILDCARD, sizeof(GUID) ) == 0 )
                            printf( "\tspecifier: KSDATAFORMAT_SPECIFIER_WILDCARD\n" );
                        else
                            printf( "\tspecifier: ?\n" );
                        */

                        /*
                            We assume that very high values for MaximumChannels are not useful and indicate
                            that the driver isn't prepared to tell us the real number of channels which it supports.
                        */
                        if( dataRangeAudio->MaximumChannels  < 0xFFFFUL && (int)dataRangeAudio->MaximumChannels > result )
                            result = (int)dataRangeAudio->MaximumChannels;
                    }
                    
                    dataRange = (KSDATARANGE*)( ((char*)dataRange) + dataRange->FormatSize);
                }

                PaUtil_FreeMemory( item );
            }
        }
    }
    
    CloseHandle( deviceHandle );
    return result;
}
Exemple #3
0
//=============================================================================
NTSTATUS                    
CMiniportWaveCyclic::ValidateFormat
(
    IN  ULONG               nPin,
    IN  PKSDATAFORMAT       pDataFormat 
)
/*++

Routine Description:

  Validates that the given dataformat is valid. This overwrites BaseWave's
  ValidateFormat and includes checks for AC3 format.

Arguments:

  pDataFormat - The dataformat for validation.

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    DPF_ENTER(("[CMiniportWaveCyclic::ValidateFormat]"));

    NTSTATUS        ntStatus = STATUS_INVALID_PARAMETER;
    PWAVEFORMATEX   pwfx;

    pwfx = GetWaveFormatEx(pDataFormat);
    if (pwfx)
    {
        if (IS_VALID_WAVEFORMATEX_GUID(&pDataFormat->SubFormat))
        {
            USHORT wfxID = EXTRACT_WAVEFORMATEX_ID(&pDataFormat->SubFormat);

            if ((wfxID == WAVE_FORMAT_PCM) ||
                ((wfxID == WAVE_FORMAT_DOLBY_AC3_SPDIF) &&
                ((nPin == KSPIN_WAVE_SPDIF_CAPTURE_HOST) || (nPin == KSPIN_WAVE_SPDIF_RENDER_HOST))))
            {
                if
                (
                    (pDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX)) &&
                    (pwfx->cbSize == 0)                              &&
                    (pwfx->nChannels <= MAX_CHANNELS )           &&
                    (pwfx->wBitsPerSample >= MIN_BITS_PER_SAMPLE)&&
                    (pwfx->wBitsPerSample <= MAX_BITS_PER_SAMPLE)&&
                    (pwfx->nSamplesPerSec >= MIN_SAMPLE_RATE)    &&
                    (pwfx->nSamplesPerSec <= MAX_SAMPLE_RATE)
                )
                {
                    ntStatus = STATUS_SUCCESS;
                }
                else
                {
                    DPF(D_TERSE, ("Invalid format"));
                }
            }
            else
            {
                DPF(D_TERSE, ("Invalid format tag"));
            }
        }
        else
        {
            DPF(D_TERSE, ("Invalid pDataFormat->SubFormat!") );
        }
    }

    return ntStatus;
} // ValidateFormat