From 21c068f1916330e90f814bed461fe0821d1665ec Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sun, 9 Oct 2011 16:36:37 +0000 Subject: checked in pd-0.43-0.src.tar.gz svn path=/trunk/; revision=15557 --- pd/portaudio/src/os/unix/pa_unix_hostapis.c | 29 ++- pd/portaudio/src/os/unix/pa_unix_util.c | 45 +++- pd/portaudio/src/os/win/pa_win_hostapis.c | 6 +- pd/portaudio/src/os/win/pa_win_util.c | 10 +- pd/portaudio/src/os/win/pa_win_waveformat.c | 154 +++++++++++++ pd/portaudio/src/os/win/pa_win_wdmks_utils.c | 260 ++++++++++++++++++++++ pd/portaudio/src/os/win/pa_win_wdmks_utils.h | 65 ++++++ pd/portaudio/src/os/win/pa_x86_plain_converters.c | 2 +- 8 files changed, 554 insertions(+), 17 deletions(-) create mode 100644 pd/portaudio/src/os/win/pa_win_waveformat.c create mode 100644 pd/portaudio/src/os/win/pa_win_wdmks_utils.c create mode 100644 pd/portaudio/src/os/win/pa_win_wdmks_utils.h (limited to 'pd/portaudio/src/os') diff --git a/pd/portaudio/src/os/unix/pa_unix_hostapis.c b/pd/portaudio/src/os/unix/pa_unix_hostapis.c index d695e1b1..339e1b14 100644 --- a/pd/portaudio/src/os/unix/pa_unix_hostapis.c +++ b/pd/portaudio/src/os/unix/pa_unix_hostapis.c @@ -1,5 +1,5 @@ /* - * $Id: pa_unix_hostapis.c 1097 2006-08-26 08:27:53Z rossb $ + * $Id: pa_unix_hostapis.c 1413 2009-05-24 17:00:36Z aknudsen $ * Portable Audio I/O Library UNIX initialization table * * Based on the Open Source API proposed by Ross Bencina @@ -49,10 +49,26 @@ PaError PaOSS_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex PaError PaSGI_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); /* Linux AudioScience HPI */ PaError PaAsiHpi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); +PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); +PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); +/** Note that on Linux, ALSA is placed before OSS so that the former is preferred over the latter. + */ PaUtilHostApiInitializer *paHostApiInitializers[] = { +#ifdef __linux__ + +#ifdef PA_USE_ALSA + PaAlsa_Initialize, +#endif + +#ifdef PA_USE_OSS + PaOSS_Initialize, +#endif + +#else /* __linux__ */ + #ifdef PA_USE_OSS PaOSS_Initialize, #endif @@ -61,6 +77,8 @@ PaUtilHostApiInitializer *paHostApiInitializers[] = PaAlsa_Initialize, #endif +#endif /* __linux__ */ + #ifdef PA_USE_JACK PaJack_Initialize, #endif @@ -72,6 +90,15 @@ PaUtilHostApiInitializer *paHostApiInitializers[] = #ifdef PA_USE_ASIHPI PaAsiHpi_Initialize, #endif + +#ifdef PA_USE_COREAUDIO + PaMacCore_Initialize, +#endif + +#ifdef PA_USE_SKELETON + PaSkeleton_Initialize, +#endif + 0 /* NULL terminated array */ }; diff --git a/pd/portaudio/src/os/unix/pa_unix_util.c b/pd/portaudio/src/os/unix/pa_unix_util.c index 1cb83875..de54e51d 100644 --- a/pd/portaudio/src/os/unix/pa_unix_util.c +++ b/pd/portaudio/src/os/unix/pa_unix_util.c @@ -1,5 +1,5 @@ /* - * $Id: pa_unix_util.c 1232 2007-06-16 14:49:43Z rossb $ + * $Id: pa_unix_util.c 1419 2009-10-22 17:28:35Z bjornroche $ * Portable Audio I/O Library * UNIX platform-specific support functions * @@ -51,6 +51,13 @@ #include #include +#if defined(__APPLE__) && !defined(HAVE_MACH_ABSOLUTE_TIME) +#define HAVE_MACH_ABSOLUTE_TIME +#endif +#ifdef HAVE_MACH_ABSOLUTE_TIME +#include +#endif + #include "pa_util.h" #include "pa_unix_util.h" #include "pa_debugprint.h" @@ -118,27 +125,47 @@ void Pa_Sleep( long msec ) #endif } -/* *** NOT USED YET: *** -static int usePerformanceCounter_; -static double microsecondsPerTick_; +#ifdef HAVE_MACH_ABSOLUTE_TIME +/* + Discussion on the CoreAudio mailing list suggests that calling + gettimeofday (or anything else in the BSD layer) is not real-time + safe, so we use mach_absolute_time on OSX. This implementation is + based on these two links: + + Technical Q&A QA1398 - Mach Absolute Time Units + http://developer.apple.com/mac/library/qa/qa2004/qa1398.html + + Tutorial: Performance and Time. + http://www.macresearch.org/tutorial_performance_and_time */ +/* Scaler to convert the result of mach_absolute_time to seconds */ +static double machSecondsConversionScaler_ = 0.0; +#endif + void PaUtil_InitializeClock( void ) { - /* TODO */ +#ifdef HAVE_MACH_ABSOLUTE_TIME + mach_timebase_info_data_t info; + kern_return_t err = mach_timebase_info( &info ); + if( err == 0 ) + machSecondsConversionScaler_ = 1e-9 * (double) info.numer / (double) info.denom; +#endif } PaTime PaUtil_GetTime( void ) { -#ifdef HAVE_CLOCK_GETTIME +#ifdef HAVE_MACH_ABSOLUTE_TIME + return mach_absolute_time() * machSecondsConversionScaler_; +#elif defined(HAVE_CLOCK_GETTIME) struct timespec tp; clock_gettime(CLOCK_REALTIME, &tp); - return (PaTime)(tp.tv_sec + tp.tv_nsec / 1.e9); + return (PaTime)(tp.tv_sec + tp.tv_nsec * 1e-9); #else struct timeval tv; gettimeofday( &tv, NULL ); - return (PaTime) tv.tv_usec / 1000000. + tv.tv_sec; + return (PaTime) tv.tv_usec * 1e-6 + tv.tv_sec; #endif } @@ -190,7 +217,7 @@ PaError PaUtil_CancelThreading( PaUtilThreading *threading, int wait, PaError *e /* paUnixMainThread * We have to be a bit careful with defining this global variable, * as explained below. */ -#ifdef __apple__ +#ifdef __APPLE__ /* apple/gcc has a "problem" with global vars and dynamic libs. Initializing it seems to fix the problem. Described a bit in this thread: diff --git a/pd/portaudio/src/os/win/pa_win_hostapis.c b/pd/portaudio/src/os/win/pa_win_hostapis.c index 83f1e914..1cca3d9f 100644 --- a/pd/portaudio/src/os/win/pa_win_hostapis.c +++ b/pd/portaudio/src/os/win/pa_win_hostapis.c @@ -1,9 +1,9 @@ /* - * $Id: pa_win_hostapis.c 1097 2006-08-26 08:27:53Z rossb $ + * $Id: pa_win_hostapis.c 1339 2008-02-15 07:50:33Z rossb $ * Portable Audio I/O Library Windows initialization table * * Based on the Open Source API proposed by Ross Bencina - * Copyright (c) 1999-2002 Ross Bencina, Phil Burk + * Copyright (c) 1999-2008 Ross Bencina, Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files @@ -39,7 +39,7 @@ /** @file @ingroup win_src - Win32 host API initialization function table. + @brief Win32 host API initialization function table. @todo Consider using PA_USE_WMME etc instead of PA_NO_WMME. This is what the Unix version does, we should consider being consistent. diff --git a/pd/portaudio/src/os/win/pa_win_util.c b/pd/portaudio/src/os/win/pa_win_util.c index 2f0cdf34..1354b9ab 100644 --- a/pd/portaudio/src/os/win/pa_win_util.c +++ b/pd/portaudio/src/os/win/pa_win_util.c @@ -1,10 +1,10 @@ /* - * $Id: pa_win_util.c 1197 2007-05-04 13:07:10Z gordon_gidluck $ + * $Id: pa_win_util.c 1410 2009-04-07 10:08:48Z rossb $ * Portable Audio I/O Library * Win32 platform-specific support functions * * Based on the Open Source API proposed by Ross Bencina - * Copyright (c) 1999-2000 Ross Bencina + * Copyright (c) 1999-2008 Ross Bencina * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files @@ -40,7 +40,7 @@ /** @file @ingroup win_src - Win32 platform-specific support functions. + @brief Win32 implementation of platform-specific PaUtil support functions. @todo Implement workaround for QueryPerformanceCounter() skipping forward bug. (see msdn kb Q274323). @@ -51,6 +51,10 @@ #include "pa_util.h" +#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */ +#pragma comment( lib, "winmm.lib" ) +#endif + /* Track memory allocations to avoid leaks. diff --git a/pd/portaudio/src/os/win/pa_win_waveformat.c b/pd/portaudio/src/os/win/pa_win_waveformat.c new file mode 100644 index 00000000..bbf616c3 --- /dev/null +++ b/pd/portaudio/src/os/win/pa_win_waveformat.c @@ -0,0 +1,154 @@ +/* + * PortAudio Portable Real-Time Audio Library + * Windows WAVEFORMAT* data structure utilities + * portaudio.h should be included before this file. + * + * Copyright (c) 2007 Ross Bencina + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ + +#include +#include + +#include "portaudio.h" +#include "pa_win_waveformat.h" + + +#if !defined(WAVE_FORMAT_EXTENSIBLE) +#define WAVE_FORMAT_EXTENSIBLE 0xFFFE +#endif + +static GUID pawin_ksDataFormatSubtypeGuidBase = + { (USHORT)(WAVE_FORMAT_PCM), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }; + + +int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat ) +{ + if( sampleFormat == paFloat32 ) + return PAWIN_WAVE_FORMAT_IEEE_FLOAT; + + return PAWIN_WAVE_FORMAT_PCM; +} + + +void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat, + int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate ) +{ + WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat; + int bytesPerSample = Pa_GetSampleSize(sampleFormat); + unsigned long bytesPerFrame = numChannels * bytesPerSample; + + waveFormatEx->wFormatTag = waveFormatTag; + waveFormatEx->nChannels = (WORD)numChannels; + waveFormatEx->nSamplesPerSec = (DWORD)sampleRate; + waveFormatEx->nAvgBytesPerSec = waveFormatEx->nSamplesPerSec * bytesPerFrame; + waveFormatEx->nBlockAlign = (WORD)bytesPerFrame; + waveFormatEx->wBitsPerSample = bytesPerSample * 8; + waveFormatEx->cbSize = 0; +} + + +void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat, + int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate, + PaWinWaveFormatChannelMask channelMask ) +{ + WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat; + int bytesPerSample = Pa_GetSampleSize(sampleFormat); + unsigned long bytesPerFrame = numChannels * bytesPerSample; + GUID guid; + + waveFormatEx->wFormatTag = WAVE_FORMAT_EXTENSIBLE; + waveFormatEx->nChannels = (WORD)numChannels; + waveFormatEx->nSamplesPerSec = (DWORD)sampleRate; + waveFormatEx->nAvgBytesPerSec = waveFormatEx->nSamplesPerSec * bytesPerFrame; + waveFormatEx->nBlockAlign = (WORD)bytesPerFrame; + waveFormatEx->wBitsPerSample = bytesPerSample * 8; + waveFormatEx->cbSize = 22; + + *((WORD*)&waveFormat->fields[PAWIN_INDEXOF_WVALIDBITSPERSAMPLE]) = + waveFormatEx->wBitsPerSample; + + *((DWORD*)&waveFormat->fields[PAWIN_INDEXOF_DWCHANNELMASK]) = channelMask; + + guid = pawin_ksDataFormatSubtypeGuidBase; + guid.Data1 = (USHORT)waveFormatTag; + *((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) = guid; +} + + +PaWinWaveFormatChannelMask PaWin_DefaultChannelMask( int numChannels ) +{ + switch( numChannels ){ + case 1: + return PAWIN_SPEAKER_MONO; + case 2: + return PAWIN_SPEAKER_STEREO; + case 3: + return PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_FRONT_RIGHT; + case 4: + return PAWIN_SPEAKER_QUAD; + case 5: + return PAWIN_SPEAKER_QUAD | PAWIN_SPEAKER_FRONT_CENTER; + case 6: + /* The meaning of the PAWIN_SPEAKER_5POINT1 flag has changed over time: + http://msdn2.microsoft.com/en-us/library/aa474707.aspx + We use PAWIN_SPEAKER_5POINT1 (not PAWIN_SPEAKER_5POINT1_SURROUND) + because on some cards (eg Audigy) PAWIN_SPEAKER_5POINT1_SURROUND + results in a virtual mixdown placing the rear output in the + front _and_ rear speakers. + */ + return PAWIN_SPEAKER_5POINT1; + /* case 7: */ + case 8: + return PAWIN_SPEAKER_7POINT1; + } + + /* Apparently some Audigy drivers will output silence + if the direct-out constant (0) is used. So this is not ideal. + */ + return PAWIN_SPEAKER_DIRECTOUT; + + /* Note that Alec Rogers proposed the following as an alternate method to + generate the default channel mask, however it doesn't seem to be an improvement + over the above, since some drivers will matrix outputs mapping to non-present + speakers accross multiple physical speakers. + + if(nChannels==1) { + pwfFormat->dwChannelMask = SPEAKER_FRONT_CENTER; + } + else { + pwfFormat->dwChannelMask = 0; + for(i=0; idwChannelMask = (pwfFormat->dwChannelMask << 1) | 0x1; + } + */ +} diff --git a/pd/portaudio/src/os/win/pa_win_wdmks_utils.c b/pd/portaudio/src/os/win/pa_win_wdmks_utils.c new file mode 100644 index 00000000..7119b43a --- /dev/null +++ b/pd/portaudio/src/os/win/pa_win_wdmks_utils.c @@ -0,0 +1,260 @@ +/* + * PortAudio Portable Real-Time Audio Library + * Windows WDM KS utilities + * + * Copyright (c) 1999 - 2007 Andrew Baldwin, Ross Bencina + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ + +#include +#include +#include +#include +#include // just for some development printfs + +#include "portaudio.h" +#include "pa_util.h" +#include "pa_win_wdmks_utils.h" + + +static PaError WdmGetPinPropertySimple( + HANDLE handle, + unsigned long pinId, + unsigned long property, + void* value, + unsigned long valueSize ) +{ + DWORD bytesReturned; + KSP_PIN ksPProp; + ksPProp.Property.Set = KSPROPSETID_Pin; + ksPProp.Property.Id = property; + ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; + ksPProp.PinId = pinId; + ksPProp.Reserved = 0; + + if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp, sizeof(KSP_PIN), + value, valueSize, &bytesReturned, NULL ) == 0 || bytesReturned != valueSize ) + { + return paUnanticipatedHostError; + } + else + { + return paNoError; + } +} + + +static PaError WdmGetPinPropertyMulti( + HANDLE handle, + unsigned long pinId, + unsigned long property, + KSMULTIPLE_ITEM** ksMultipleItem) +{ + unsigned long multipleItemSize = 0; + KSP_PIN ksPProp; + DWORD bytesReturned; + + *ksMultipleItem = 0; + + ksPProp.Property.Set = KSPROPSETID_Pin; + ksPProp.Property.Id = property; + ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; + ksPProp.PinId = pinId; + ksPProp.Reserved = 0; + + if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp.Property, + sizeof(KSP_PIN), NULL, 0, &multipleItemSize, NULL ) == 0 && GetLastError() != ERROR_MORE_DATA ) + { + return paUnanticipatedHostError; + } + + *ksMultipleItem = (KSMULTIPLE_ITEM*)PaUtil_AllocateMemory( multipleItemSize ); + if( !*ksMultipleItem ) + { + return paInsufficientMemory; + } + + if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp, sizeof(KSP_PIN), + (void*)*ksMultipleItem, multipleItemSize, &bytesReturned, NULL ) == 0 || bytesReturned != multipleItemSize ) + { + PaUtil_FreeMemory( ksMultipleItem ); + return paUnanticipatedHostError; + } + + return paNoError; +} + + +static int GetKSFilterPinCount( HANDLE deviceHandle ) +{ + DWORD result; + + if( WdmGetPinPropertySimple( deviceHandle, 0, KSPROPERTY_PIN_CTYPES, &result, sizeof(result) ) == paNoError ){ + return result; + }else{ + return 0; + } +} + + +static KSPIN_COMMUNICATION GetKSFilterPinPropertyCommunication( HANDLE deviceHandle, int pinId ) +{ + KSPIN_COMMUNICATION result; + + if( WdmGetPinPropertySimple( deviceHandle, pinId, KSPROPERTY_PIN_COMMUNICATION, &result, sizeof(result) ) == paNoError ){ + return result; + }else{ + return KSPIN_COMMUNICATION_NONE; + } +} + + +static KSPIN_DATAFLOW GetKSFilterPinPropertyDataflow( HANDLE deviceHandle, int pinId ) +{ + KSPIN_DATAFLOW result; + + if( WdmGetPinPropertySimple( deviceHandle, pinId, KSPROPERTY_PIN_DATAFLOW, &result, sizeof(result) ) == paNoError ){ + return result; + }else{ + return (KSPIN_DATAFLOW)0; + } +} + + +static int KSFilterPinPropertyIdentifiersInclude( + HANDLE deviceHandle, int pinId, unsigned long property, const GUID *identifierSet, unsigned long identifierId ) +{ + KSMULTIPLE_ITEM* item = NULL; + KSIDENTIFIER* identifier; + int i; + int result = 0; + + if( WdmGetPinPropertyMulti( deviceHandle, pinId, property, &item) != paNoError ) + return 0; + + identifier = (KSIDENTIFIER*)(item+1); + + for( i = 0; i < (int)item->Count; i++ ) + { + if( !memcmp( (void*)&identifier[i].Set, (void*)identifierSet, sizeof( GUID ) ) && + ( identifier[i].Id == identifierId ) ) + { + result = 1; + break; + } + } + + PaUtil_FreeMemory( item ); + + return result; +} + + +/* 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; +} diff --git a/pd/portaudio/src/os/win/pa_win_wdmks_utils.h b/pd/portaudio/src/os/win/pa_win_wdmks_utils.h new file mode 100644 index 00000000..f54035f4 --- /dev/null +++ b/pd/portaudio/src/os/win/pa_win_wdmks_utils.h @@ -0,0 +1,65 @@ +#ifndef PA_WIN_WDMKS_UTILS_H +#define PA_WIN_WDMKS_UTILS_H + +/* + * PortAudio Portable Real-Time Audio Library + * Windows WDM KS utilities + * + * Copyright (c) 1999 - 2007 Ross Bencina, Andrew Baldwin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ + +/** @file + @brief Utilities for working with the Windows WDM KS API +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Query for the maximum number of channels supported by any pin of the + specified device. Returns 0 if the query fails for any reason. + + @param wcharDevicePath A system level PnP interface path, supplied as a WCHAR unicode string. + Declard as void* to avoid introducing a dependency on wchar_t here. + + @param isInput A flag specifying whether to query for input (non-zero) or output (zero) channels. +*/ +int PaWin_WDMKS_QueryFilterMaximumChannelCount( void *wcharDevicePath, int isInput ); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* PA_WIN_WDMKS_UTILS_H */ \ No newline at end of file diff --git a/pd/portaudio/src/os/win/pa_x86_plain_converters.c b/pd/portaudio/src/os/win/pa_x86_plain_converters.c index 63b058df..d3d0fdaf 100644 --- a/pd/portaudio/src/os/win/pa_x86_plain_converters.c +++ b/pd/portaudio/src/os/win/pa_x86_plain_converters.c @@ -124,7 +124,7 @@ static const double ditheredInt16Scaler_ = 0x7FFE; #define PA_DITHER_BITS_ (15) /* Multiply by PA_FLOAT_DITHER_SCALE_ to get a float between -2.0 and +1.99999 */ -#define PA_FLOAT_DITHER_SCALE_ (1.0 / ((1<