aboutsummaryrefslogtreecommitdiff
path: root/pd/portaudio/src/os
diff options
context:
space:
mode:
Diffstat (limited to 'pd/portaudio/src/os')
-rw-r--r--pd/portaudio/src/os/unix/pa_unix_hostapis.c29
-rw-r--r--pd/portaudio/src/os/unix/pa_unix_util.c45
-rw-r--r--pd/portaudio/src/os/win/pa_win_hostapis.c6
-rw-r--r--pd/portaudio/src/os/win/pa_win_util.c10
-rw-r--r--pd/portaudio/src/os/win/pa_win_waveformat.c154
-rw-r--r--pd/portaudio/src/os/win/pa_win_wdmks_utils.c260
-rw-r--r--pd/portaudio/src/os/win/pa_win_wdmks_utils.h65
-rw-r--r--pd/portaudio/src/os/win/pa_x86_plain_converters.c2
8 files changed, 554 insertions, 17 deletions
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 <math.h>
#include <errno.h>
+#if defined(__APPLE__) && !defined(HAVE_MACH_ABSOLUTE_TIME)
+#define HAVE_MACH_ABSOLUTE_TIME
+#endif
+#ifdef HAVE_MACH_ABSOLUTE_TIME
+#include <mach/mach_time.h>
+#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 <windows.h>
+#include <mmsystem.h>
+
+#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; i<nChannels; i++)
+ pwfFormat->dwChannelMask = (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 <windows.h>
+#include <mmreg.h>
+#include <ks.h>
+#include <ksmedia.h>
+#include <stdio.h> // 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<<PA_DITHER_BITS_)-1))
+#define PA_FLOAT_DITHER_SCALE_ (1.0F / ((1<<PA_DITHER_BITS_)-1))
static const float const_float_dither_scale_ = PA_FLOAT_DITHER_SCALE_;
#define PA_DITHER_SHIFT_ ((32 - PA_DITHER_BITS_) + 1)