diff --git a/portaudio/unused/SConscript b/portaudio/unused/SConscript
deleted file mode 100644
index a5dd47f240556afb076aec03b57288c49a02996e..0000000000000000000000000000000000000000
--- a/portaudio/unused/SConscript
+++ /dev/null
@@ -1,205 +0,0 @@
-import os.path, copy, sys
-
-def checkSymbol(conf, header, library=None, symbol=None, autoAdd=True, critical=False, pkgName=None):
-    """ Check for symbol in library, optionally look only for header.
-    @param conf: Configure instance.
-    @param header: The header file where the symbol is declared.
-    @param library: The library in which the symbol exists, if None it is taken to be the standard C library.
-    @param symbol: The symbol to look for, if None only the header will be looked up.
-    @param autoAdd: Automatically link with this library if check is positive.
-    @param critical: Raise on error?
-    @param pkgName: Optional name of pkg-config entry for library, to determine build parameters.
-    @return: True/False
-    """
-    origEnv = conf.env.Copy() # Copy unmodified environment so we can restore it upon error
-    env = conf.env
-    if library is None:
-        library = "c"   # Standard library
-        autoAdd = False
-
-    if pkgName is not None:
-        origLibs = copy.copy(env.get("LIBS", None))
-
-        try: env.ParseConfig("pkg-config --silence-errors %s --cflags --libs" % pkgName)
-        except: pass
-        else:
-            # I see no other way of checking that the parsing succeeded, if it did add no more linking parameters
-            if env.get("LIBS", None) != origLibs:
-                autoAdd = False
-
-    try:
-        if not conf.CheckCHeader(header, include_quotes="<>"):
-            raise ConfigurationError("missing header %s" % header)
-        if symbol is not None and not conf.CheckLib(library, symbol, language="C", autoadd=autoAdd):
-            raise ConfigurationError("missing symbol %s in library %s" % (symbol, library))
-    except ConfigurationError:
-        conf.env = origEnv
-        if not critical:
-            return False
-        raise
-
-    return True
-
-import SCons.Errors
-
-# Import common variables
-
-# Could use '#' to refer to top-level SConstruct directory, but looks like env.SConsignFile doesn't interpret this at least :(
-sconsDir = os.path.abspath(os.path.join("build", "scons"))
-
-try:
-    Import("Platform", "Posix", "ConfigurationError", "ApiVer")
-except SCons.Errors.UserError:
-    # The common objects must be exported first
-    SConscript(os.path.join(sconsDir, "SConscript_common"))
-    Import("Platform", "Posix", "ConfigurationError", "ApiVer")
-
-Import("env")
-
-# This will be manipulated
-env = env.Copy()
-
-# We operate with a set of needed libraries and optional libraries, the latter stemming from host API implementations.
-# For libraries of both types we record a set of values that is used to look for the library in question, during
-# configuration. If the corresponding library for a host API implementation isn't found, the implementation is left out.
-neededLibs = []
-optionalImpls = {}
-if Platform in Posix:
-    env.Append(CPPPATH=os.path.join("os", "unix"))
-    neededLibs += [("pthread", "pthread.h", "pthread_create"), ("m", "math.h", "sin")]
-    if env["useALSA"]:
-        optionalImpls["ALSA"] = ("asound", "alsa/asoundlib.h", "snd_pcm_open")
-    if env["useJACK"]:
-        optionalImpls["JACK"] = ("jack", "jack/jack.h", "jack_client_new")
-    if env["useOSS"]:
-        # TODO: It looks like the prefix for soundcard.h depends on the platform
-        optionalImpls["OSS"] = ("oss", "sys/soundcard.h", None)
-    if env["useASIHPI"]:
-        optionalImpls["ASIHPI"] = ("hpi", "asihpi/hpi.h", "HPI_SubSysCreate")
-else:
-    raise ConfigurationError("unknown platform %s" % Platform)
-
-if Platform == "darwin":
-    env.Append(LINKFLAGS=["-framework CoreAudio", "-framework AudioToolBox"])
-    env.Append(CPPDEFINES=["PA_USE_COREAUDIO"])
-elif Platform == "cygwin":
-    env.Append(LIBS=["winmm"])
-elif Platform == "irix":
-    neededLibs +=  [("audio", "dmedia/audio.h", "alOpenPort"), ("dmedia", "dmedia/dmedia.h", "dmGetUST")]
-    env.Append(CPPDEFINES=["PA_USE_SGI"])
-
-def CheckCTypeSize(context, tp):
-    """ Check size of C type.
-    @param context: A configuration context.
-    @param tp: The type to check.
-    @return: Size of type, in bytes.
-    """
-    context.Message("Checking the size of C type %s..." % tp)
-    ret = context.TryRun("""
-#include <stdio.h>
-
-int main() {
-    printf("%%d", sizeof(%s));
-    return 0;
-}
-""" % tp, ".c")
-    if not ret[0]:
-        context.Result(" Couldn't obtain size of type %s!" % tp)
-        return None
-
-    assert ret[1]
-    sz = int(ret[1])
-    context.Result("%d" % sz)
-    return sz
-
-"""
-if sys.byteorder == "little":
-    env.Append(CPPDEFINES=["PA_LITTLE_ENDIAN"])
-elif sys.byteorder == "big":
-    env.Append(CPPDEFINES=["PA_BIG_ENDIAN"])
-else:
-    raise ConfigurationError("unknown byte order: %s" % sys.byteorder)
-"""
-if env["enableDebugOutput"]:
-    env.Append(CPPDEFINES=["PA_ENABLE_DEBUG_OUTPUT"])
-
-# Start configuration
-
-# Use an absolute path for conf_dir, otherwise it gets created both relative to current directory and build directory
-conf = env.Configure(log_file=os.path.join(sconsDir, "sconf.log"), custom_tests={"CheckCTypeSize": CheckCTypeSize},
-        conf_dir=os.path.join(sconsDir, ".sconf_temp"))
-conf.env.Append(CPPDEFINES=["SIZEOF_SHORT=%d" % conf.CheckCTypeSize("short")])
-conf.env.Append(CPPDEFINES=["SIZEOF_INT=%d" % conf.CheckCTypeSize("int")])
-conf.env.Append(CPPDEFINES=["SIZEOF_LONG=%d" % conf.CheckCTypeSize("long")])
-if checkSymbol(conf, "time.h", "rt", "clock_gettime"):
-    conf.env.Append(CPPDEFINES=["HAVE_CLOCK_GETTIME"])
-if checkSymbol(conf, "time.h", symbol="nanosleep"):
-    conf.env.Append(CPPDEFINES=["HAVE_NANOSLEEP"])
-if conf.CheckCHeader("sys/soundcard.h"):
-    conf.env.Append(CPPDEFINES=["HAVE_SYS_SOUNDCARD_H"])
-if conf.CheckCHeader("linux/soundcard.h"):
-    conf.env.Append(CPPDEFINES=["HAVE_LINUX_SOUNDCARD_H"])
-if conf.CheckCHeader("machine/soundcard.h"):
-    conf.env.Append(CPPDEFINES=["HAVE_MACHINE_SOUNDCARD_H"])
-
-# Look for needed libraries and link with them
-for lib, hdr, sym in neededLibs:
-    checkSymbol(conf, hdr, lib, sym, critical=True)
-# Look for host API libraries, if a library isn't found disable corresponding host API implementation.
-for name, val in optionalImpls.items():
-    lib, hdr, sym = val
-    if checkSymbol(conf, hdr, lib, sym, critical=False, pkgName=name.lower()):
-        conf.env.Append(CPPDEFINES=["PA_USE_%s=1" % name.upper()])
-    else:
-        del optionalImpls[name]
-
-# Configuration finished
-env = conf.Finish()
-
-# PA infrastructure
-CommonSources = [os.path.join("common", f) for f in "pa_allocation.c pa_converters.c pa_cpuload.c pa_dither.c pa_front.c \
-        pa_process.c pa_skeleton.c pa_stream.c pa_trace.c pa_debugprint.c pa_ringbuffer.c".split()]
-
-# Host API implementations
-ImplSources = []
-if Platform in Posix:
-    ImplSources += [os.path.join("os", "unix", f) for f in "pa_unix_hostapis.c pa_unix_util.c".split()]
-
-if "ALSA" in optionalImpls:
-    ImplSources.append(os.path.join("hostapi", "alsa", "pa_linux_alsa.c"))
-if "JACK" in optionalImpls:
-    ImplSources.append(os.path.join("hostapi", "jack", "pa_jack.c"))
-if "OSS" in optionalImpls:
-    ImplSources.append(os.path.join("hostapi", "oss", "pa_unix_oss.c"))
-if "ASIHPI" in optionalImpls:
-    ImplSources.append(os.path.join("hostapi", "asihpi", "pa_linux_asihpi.c"))
-
-
-sources = CommonSources + ImplSources
-
-sharedLibEnv = env.Copy()
-if Platform in Posix:
-    # Add soname to library, this is so a reference is made to the versioned library in programs linking against libportaudio.so
-    sharedLibEnv.AppendUnique(SHLINKFLAGS="-Wl,-soname=libportaudio.so.%d" % int(ApiVer.split(".")[0]))
-sharedLib = sharedLibEnv.SharedLibrary(target="portaudio", source=sources)
-
-staticLib = env.StaticLibrary(target="portaudio", source=sources)
-
-if Platform in Posix:
-    prefix = env["prefix"]
-    includeDir = os.path.join(prefix, "include")
-    libDir = os.path.join(prefix, "lib")
-
-testNames = ["patest_sine", "paqa_devs", "paqa_errs", "patest1", "patest_buffer", "patest_callbackstop", "patest_clip", \
-        "patest_dither", "patest_hang", "patest_in_overflow", "patest_latency", "patest_leftright", "patest_longsine", \
-        "patest_many", "patest_maxsines", "patest_multi_sine", "patest_out_underflow", "patest_pink", "patest_prime", \
-        "patest_read_record", "patest_record", "patest_ringmix", "patest_saw", "patest_sine8", "patest_sine", \
-        "patest_sine_time", "patest_start_stop", "patest_stop", "patest_sync", "patest_toomanysines", \
-        "patest_underflow", "patest_wire", "patest_write_sine", "pa_devs", "pa_fuzz", "pa_minlat", \
-        "patest_sine_channelmaps",]
-
-# The test directory ("bin") should be in the top-level PA directory
-tests = [env.Program(target=os.path.join("#", "bin", name), source=[os.path.join("#", "test", name + ".c"),
-        staticLib]) for name in testNames]
-
-Return("sources", "sharedLib", "staticLib", "tests", "env")
diff --git a/portaudio/unused/hostapi/asihpi/pa_linux_asihpi.c b/portaudio/unused/hostapi/asihpi/pa_linux_asihpi.c
deleted file mode 100644
index e969d693aa225a301ccbe0ae7d0c187d26b40bf1..0000000000000000000000000000000000000000
--- a/portaudio/unused/hostapi/asihpi/pa_linux_asihpi.c
+++ /dev/null
@@ -1,2910 +0,0 @@
-/*
- * PortAudio Portable Real-Time Audio Library
- * Latest Version at: http://www.portaudio.com
- *
- * PortAudio v18 version of AudioScience HPI driver by Fred Gleason <fredg@salemradiolabs.com>
- * PortAudio v19 version of AudioScience HPI driver by Ludwig Schwardt <schwardt@sun.ac.za>
- *
- * Copyright (c) 2003 Fred Gleason
- * Copyright (c) 2005,2006 Ludwig Schwardt
- *
- * 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.
- */
-
-/*
- * Modification History
- * 12/2003 - Initial version
- * 09/2005 - v19 version [rewrite]
- */
-
-/** @file
- @ingroup hostapi_src
- @brief Host API implementation supporting AudioScience cards
-        via the Linux HPI interface.
-
- <h3>Overview</h3>
-
- This is a PortAudio implementation for the AudioScience HPI Audio API
- on the Linux platform. AudioScience makes a range of audio adapters customised
- for the broadcasting industry, with support for both Windows and Linux.
- More information on their products can be found on their website:
-
-     http://www.audioscience.com
-
- Documentation for the HPI API can be found at:
-
-     http://www.audioscience.com/internet/download/sdk/spchpi.pdf
-
- The Linux HPI driver itself (a kernel module + library) can be downloaded from:
-
-     http://www.audioscience.com/internet/download/linux_drivers.htm
-
- <h3>Implementation strategy</h3>
-
- *Note* Ideally, AudioScience cards should be handled by the PortAudio ALSA
- implementation on Linux, as ALSA is the preferred Linux soundcard API. The existence
- of this host API implementation might therefore seem a bit flawed. Unfortunately, at
- the time of the creation of this implementation (June 2006), the PA ALSA implementation
- could not make use of the existing AudioScience ALSA driver. PA ALSA uses the
- "memory-mapped" (mmap) ALSA access mode to interact with the ALSA library, while the
- AudioScience ALSA driver only supports the "read-write" access mode. The appropriate
- solution to this problem is to add "read-write" support to PortAudio ALSA, thereby
- extending the range of soundcards it supports (AudioScience cards are not the only
- ones with this problem). Given the author's limited knowledge of ALSA and the
- simplicity of the HPI API, the second-best solution was born...
-
- The following mapping between HPI and PA was followed:
- HPI subsystem => PortAudio host API
- HPI adapter => nothing specific
- HPI stream => PortAudio device
-
- Each HPI stream is either input or output (not both), and can support
- different channel counts, sampling rates and sample formats. It is therefore
- a more natural fit to a PA device. A PA stream can therefore combine two
- HPI streams (one input and one output) into a "full-duplex" stream. These
- HPI streams can even be on different physical adapters. The two streams ought to be
- sample-synchronised when they reside on the same adapter, as most AudioScience adapters
- derive their ADC and DAC clocks from one master clock. When combining two adapters
- into one full-duplex stream, however, the use of a word clock connection between the
- adapters is strongly recommended.
-
- The HPI interface is inherently blocking, making use of read and write calls to
- transfer data between user buffers and driver buffers. The callback interface therefore
- requires a helper thread ("callback engine") which periodically transfers data (one thread
- per PA stream, in fact). The current implementation explicitly sleeps via Pa_Sleep() until
- enough samples can be transferred (select() or poll() would be better, but currently seems
- impossible...). The thread implementation makes use of the Unix thread helper functions
- and some pthread calls here and there. If a unified PA thread exists, this host API
- implementation might also compile on Windows, as this is the only real Linux-specific
- part of the code.
-
- There is no inherent fixed buffer size in the HPI interface, as in some other host APIs.
- The PortAudio implementation contains a buffer that is allocated during OpenStream and
- used to transfer data between the callback and the HPI driver buffer. The size of this
- buffer is quite flexible and is derived from latency suggestions and matched to the
- requested callback buffer size as far as possible. It can become quite huge, as the
- AudioScience cards are typically geared towards higher-latency applications and contain
- large hardware buffers.
-
- The HPI interface natively supports most common sample formats and sample rates (some
- conversion is done on the adapter itself).
-
- Stream time is measured based on the number of processed frames, which is adjusted by the
- number of frames currently buffered by the HPI driver.
-
- There is basic support for detecting overflow and underflow. The HPI interface does not
- explicitly indicate this, so thresholds on buffer levels are used in combination with
- stream state. Recovery from overflow and underflow is left to the PA client.
-
- Blocking streams are also implemented. It makes use of the same polling routines that
- the callback interface uses, in order to prevent the allocation of variable-sized
- buffers during reading and writing. The framesPerBuffer parameter is therefore still
- relevant, and this can be increased in the blocking case to improve efficiency.
-
- The implementation contains extensive reporting macros (slightly modified PA_ENSURE and
- PA_UNLESS versions) and a useful stream dump routine to provide debugging feedback.
-
- Output buffer priming via the user callback (i.e. paPrimeOutputBuffersUsingStreamCallback
- and friends) is not implemented yet. All output is primed with silence.
-
- Please send bug reports etc. to Ludwig Schwardt <schwardt@sun.ac.za>
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>          /* strlen() */
-#include <pthread.h>         /* pthreads and friends */
-#include <assert.h>          /* assert */
-#include <math.h>            /* ceil, floor */
-
-#include <asihpi/hpi.h>      /* HPI API */
-
-#include "portaudio.h"       /* PortAudio API */
-#include "pa_util.h"         /* PA_DEBUG, other small utilities */
-#include "pa_unix_util.h"    /* Unix threading utilities */
-#include "pa_allocation.h"   /* Group memory allocation */
-#include "pa_hostapi.h"      /* Host API structs */
-#include "pa_stream.h"       /* Stream interface structs */
-#include "pa_cpuload.h"      /* CPU load measurer */
-#include "pa_process.h"      /* Buffer processor */
-#include "pa_converters.h"   /* PaUtilZeroer */
-#include "pa_debugprint.h"
-
-/* -------------------------------------------------------------------------- */
-
-/*
- * Defines
- */
-
-/* Error reporting and assertions */
-
-/** Evaluate expression, and return on any PortAudio errors */
-#define PA_ENSURE_(expr) \
-    do { \
-        PaError paError = (expr); \
-        if( UNLIKELY( paError < paNoError ) ) \
-        { \
-            PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
-            result = paError; \
-            goto error; \
-        } \
-    } while (0);
-
-/** Assert expression, else return the provided PaError */
-#define PA_UNLESS_(expr, paError) \
-    do { \
-        if( UNLIKELY( (expr) == 0 ) ) \
-        { \
-            PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
-            result = (paError); \
-            goto error; \
-        } \
-    } while( 0 );
-
-/** Check return value of HPI function, and map it to PaError */
-#define PA_ASIHPI_UNLESS_(expr, paError) \
-    do { \
-        HW16 hpiError = (expr); \
-        /* If HPI error occurred */ \
-        if( UNLIKELY( hpiError ) ) \
-        { \
-	    char szError[256]; \
-	    HPI_GetErrorText( hpiError, szError ); \
-	    PA_DEBUG(( "HPI error %d occurred: %s\n", hpiError, szError )); \
-	    /* This message will always be displayed, even if debug info is disabled */ \
-            PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
-            if( (paError) == paUnanticipatedHostError ) \
-	    { \
-	        PA_DEBUG(( "Host error description: %s\n", szError )); \
-	        /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \
-	        if( pthread_equal( pthread_self(), paUnixMainThread ) ) \
-                { \
-		    PaUtil_SetLastHostErrorInfo( paInDevelopment, hpiError, szError ); \
-                } \
-	    } \
-	    /* If paNoError is specified, continue as usual */ \
-            /* (useful if you only want to print out the debug messages above) */ \
-	    if( (paError) < 0 ) \
-	    { \
-	        result = (paError); \
-	        goto error; \
-	    } \
-        } \
-    } while( 0 );
-
-/** Report HPI error code and text */
-#define PA_ASIHPI_REPORT_ERROR_(hpiErrorCode) \
-    do { \
-        char szError[256]; \
-        HPI_GetErrorText( hpiError, szError ); \
-        PA_DEBUG(( "HPI error %d occurred: %s\n", hpiError, szError )); \
-        /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \
-        if( pthread_equal( pthread_self(), paUnixMainThread ) ) \
-	{ \
-	    PaUtil_SetLastHostErrorInfo( paInDevelopment, (hpiErrorCode), szError ); \
-	} \
-    } while( 0 );
-
-/* Defaults */
-
-/** Sample formats available natively on AudioScience hardware */
-#define PA_ASIHPI_AVAILABLE_FORMATS_ (paFloat32 | paInt32 | paInt24 | paInt16 | paUInt8)
-/** Enable background bus mastering (BBM) for buffer transfers, if available (see HPI docs) */
-#define PA_ASIHPI_USE_BBM_ 1
-/** Minimum number of frames in HPI buffer (for either data or available space).
- If buffer contains less data/space, it indicates xrun or completion. */
-#define PA_ASIHPI_MIN_FRAMES_ 1152
-/** Minimum polling interval in milliseconds, which determines minimum host buffer size */
-#define PA_ASIHPI_MIN_POLLING_INTERVAL_ 10
-
-/* -------------------------------------------------------------------------- */
-
-/*
- * Structures
- */
-
-/** Host API global data */
-typedef struct PaAsiHpiHostApiRepresentation
-{
-    /* PortAudio "base class" - keep the baseRep first! (C-style inheritance) */
-    PaUtilHostApiRepresentation baseHostApiRep;
-    PaUtilStreamInterface callbackStreamInterface;
-    PaUtilStreamInterface blockingStreamInterface;
-
-    PaUtilAllocationGroup *allocations;
-
-    /* implementation specific data goes here */
-
-    PaHostApiIndex hostApiIndex;
-    /** HPI subsystem pointer */
-    HPI_HSUBSYS *subSys;
-}
-PaAsiHpiHostApiRepresentation;
-
-
-/** Device data */
-typedef struct PaAsiHpiDeviceInfo
-{
-    /* PortAudio "base class" - keep the baseRep first! (C-style inheritance) */
-    /** Common PortAudio device information */
-    PaDeviceInfo baseDeviceInfo;
-
-    /* implementation specific data goes here */
-
-    /** HPI subsystem (required for most HPI calls) */
-    HPI_HSUBSYS *subSys;
-    /** Adapter index */
-    HW16 adapterIndex;
-    /** Adapter model number (hex) */
-    HW16 adapterType;
-    /** Adapter HW/SW version */
-    HW16 adapterVersion;
-    /** Adapter serial number */
-    HW32 adapterSerialNumber;
-    /** Stream number */
-    HW16 streamIndex;
-    /** 0=Input, 1=Output (HPI streams are either input or output but not both) */
-    HW16 streamIsOutput;
-}
-PaAsiHpiDeviceInfo;
-
-
-/** Stream state as defined by PortAudio.
- It seems that the host API implementation has to keep track of the PortAudio stream state.
- Please note that this is NOT the same as the state of the underlying HPI stream. By separating
- these two concepts, a lot of flexibility is gained. There is a rough match between the two,
- of course, but forcing a precise match is difficult. For example, HPI_STATE_DRAINED can occur
- during the Active state of PortAudio (due to underruns) and also during CallBackFinished in
- the case of an output stream. Similarly, HPI_STATE_STOPPED mostly coincides with the Stopped
- PortAudio state, by may also occur in the CallbackFinished state when recording is finished.
-
- Here is a rough match-up:
-
- PortAudio state   =>     HPI state
- ---------------          ---------
- Active            =>     HPI_STATE_RECORDING, HPI_STATE_PLAYING, (HPI_STATE_DRAINED)
- Stopped           =>     HPI_STATE_STOPPED
- CallbackFinished  =>     HPI_STATE_STOPPED, HPI_STATE_DRAINED */
-typedef enum PaAsiHpiStreamState
-{
-    paAsiHpiStoppedState=0,
-    paAsiHpiActiveState=1,
-    paAsiHpiCallbackFinishedState=2
-}
-PaAsiHpiStreamState;
-
-
-/** Stream component data (associated with one direction, i.e. either input or output) */
-typedef struct PaAsiHpiStreamComponent
-{
-    /** Device information (HPI handles, etc) */
-    PaAsiHpiDeviceInfo *hpiDevice;
-    /** Stream handle, as passed to HPI interface.
-     HACK: we assume types HPI_HISTREAM and HPI_HOSTREAM are the same...
-     (both are HW32 up to version 3.00 of ASIHPI, and hopefully they stay that way) */
-    HPI_HISTREAM hpiStream;
-    /** Stream format, as passed to HPI interface */
-    HPI_FORMAT hpiFormat;
-    /** Number of bytes per frame, derived from hpiFormat and saved for convenience */
-    HW32 bytesPerFrame;
-    /** Size of hardware (on-card) buffer of stream in bytes */
-    HW32 hardwareBufferSize;
-    /** Size of host (BBM) buffer of stream in bytes (if used) */
-    HW32 hostBufferSize;
-    /** Upper limit on the utilization of output stream buffer (both hardware and host).
-     This prevents large latencies in an output-only stream with a potentially huge buffer
-     and a fast data generator, which would otherwise keep the hardware buffer filled to
-     capacity. See also the "Hardware Buffering=off" option in the AudioScience WAV driver. */
-    HW32 outputBufferCap;
-    /** Sample buffer (halfway station between HPI and buffer processor) */
-    HW8 *tempBuffer;
-    /** Sample buffer size, in bytes */
-    HW32 tempBufferSize;
-}
-PaAsiHpiStreamComponent;
-
-
-/** Stream data */
-typedef struct PaAsiHpiStream
-{
-    /* PortAudio "base class" - keep the baseRep first! (C-style inheritance) */
-    PaUtilStreamRepresentation baseStreamRep;
-    PaUtilCpuLoadMeasurer cpuLoadMeasurer;
-    PaUtilBufferProcessor bufferProcessor;
-
-    PaUtilAllocationGroup *allocations;
-
-    /* implementation specific data goes here */
-
-    /** Separate structs for input and output sides of stream */
-    PaAsiHpiStreamComponent *input, *output;
-
-    /** Polling interval (in milliseconds) */
-    HW32 pollingInterval;
-    /** Are we running in callback mode? */
-    int callbackMode;
-    /** Number of frames to transfer at a time to/from HPI */
-    unsigned long maxFramesPerHostBuffer;
-    /** Indicates that the stream is in the paNeverDropInput mode */
-    int neverDropInput;
-    /** Contains copy of user buffers, used by blocking interface to transfer non-interleaved data.
-     It went here instead of to each stream component, as the stream component buffer setup in
-     PaAsiHpi_SetupBuffers doesn't know the stream details such as callbackMode.
-     (Maybe a problem later if ReadStream and WriteStream happens concurrently on same stream.) */
-    void **blockingUserBufferCopy;
-
-    /* Thread-related variables */
-
-    /** Helper thread which will deliver data to user callback */
-    PaUnixThread thread;
-    /** PortAudio stream state (Active/Stopped/CallbackFinished) */
-    volatile sig_atomic_t state;
-    /** Hard abort, i.e. drop frames? */
-    volatile sig_atomic_t callbackAbort;
-    /** True if stream stopped via exiting callback with paComplete/paAbort flag
-     (as opposed to explicit call to StopStream/AbortStream) */
-    volatile sig_atomic_t callbackFinished;
-}
-PaAsiHpiStream;
-
-
-/** Stream state information, collected together for convenience */
-typedef struct PaAsiHpiStreamInfo
-{
-    /** HPI stream state (HPI_STATE_STOPPED, HPI_STATE_PLAYING, etc.) */
-    HW16 state;
-    /** Size (in bytes) of recording/playback data buffer in HPI driver */
-    HW32 bufferSize;
-    /** Amount of data (in bytes) available in the buffer */
-    HW32 dataSize;
-    /** Number of frames played/recorded since last stream reset */
-    HW32 frameCounter;
-    /** Amount of data (in bytes) in hardware (on-card) buffer.
-     This differs from dataSize if bus mastering (BBM) is used, which introduces another
-     driver-level buffer to which dataSize/bufferSize then refers. */
-    HW32 auxDataSize;
-    /** Total number of data frames currently buffered by HPI driver (host + hw buffers) */
-    HW32 totalBufferedData;
-    /** Size of immediately available data (for input) or space (for output) in frames.
-     This only checks the first-level buffer (typically host buffer). This amount can be
-     transferred immediately. */
-    HW32 availableFrames;
-    /** Indicates that hardware buffer is getting too full */
-    int overflow;
-    /** Indicates that hardware buffer is getting too empty */
-    int underflow;
-}
-PaAsiHpiStreamInfo;
-
-/* -------------------------------------------------------------------------- */
-
-/*
- * Function prototypes
- */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-    /* The only exposed function in the entire host API implementation */
-    PaError PaAsiHpi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
-static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
-                                  const PaStreamParameters *inputParameters,
-                                  const PaStreamParameters *outputParameters,
-                                  double sampleRate );
-
-/* Stream prototypes */
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
-                           PaStream **s,
-                           const PaStreamParameters *inputParameters,
-                           const PaStreamParameters *outputParameters,
-                           double sampleRate,
-                           unsigned long framesPerBuffer,
-                           PaStreamFlags streamFlags,
-                           PaStreamCallback *streamCallback,
-                           void *userData );
-static PaError CloseStream( PaStream *s );
-static PaError StartStream( PaStream *s );
-static PaError StopStream( PaStream *s );
-static PaError AbortStream( PaStream *s );
-static PaError IsStreamStopped( PaStream *s );
-static PaError IsStreamActive( PaStream *s );
-static PaTime GetStreamTime( PaStream *s );
-static double GetStreamCpuLoad( PaStream *s );
-
-/* Blocking prototypes */
-static PaError ReadStream( PaStream *s, void *buffer, unsigned long frames );
-static PaError WriteStream( PaStream *s, const void *buffer, unsigned long frames );
-static signed long GetStreamReadAvailable( PaStream *s );
-static signed long GetStreamWriteAvailable( PaStream *s );
-
-/* Callback prototypes */
-static void *CallbackThreadFunc( void *userData );
-
-/* Functions specific to this API */
-static PaError PaAsiHpi_BuildDeviceList( PaAsiHpiHostApiRepresentation *hpiHostApi );
-static HW16 PaAsiHpi_PaToHpiFormat( PaSampleFormat paFormat );
-static PaSampleFormat PaAsiHpi_HpiToPaFormat( HW16 hpiFormat );
-static PaError PaAsiHpi_CreateFormat( struct PaUtilHostApiRepresentation *hostApi,
-                                      const PaStreamParameters *parameters, double sampleRate,
-                                      PaAsiHpiDeviceInfo **hpiDevice, HPI_FORMAT *hpiFormat );
-static PaError PaAsiHpi_OpenInput( struct PaUtilHostApiRepresentation *hostApi,
-                                   const PaAsiHpiDeviceInfo *hpiDevice, const HPI_FORMAT *hpiFormat,
-                                   HPI_HISTREAM *hpiStream );
-static PaError PaAsiHpi_OpenOutput( struct PaUtilHostApiRepresentation *hostApi,
-                                    const PaAsiHpiDeviceInfo *hpiDevice, const HPI_FORMAT *hpiFormat,
-                                    HPI_HOSTREAM *hpiStream );
-static PaError PaAsiHpi_GetStreamInfo( PaAsiHpiStreamComponent *streamComp, PaAsiHpiStreamInfo *info );
-static void PaAsiHpi_StreamComponentDump( PaAsiHpiStreamComponent *streamComp, PaAsiHpiStream *stream );
-static void PaAsiHpi_StreamDump( PaAsiHpiStream *stream );
-static PaError PaAsiHpi_SetupBuffers( PaAsiHpiStreamComponent *streamComp, HW32 pollingInterval,
-                                      unsigned long framesPerPaHostBuffer, PaTime suggestedLatency );
-static PaError PaAsiHpi_PrimeOutputWithSilence( PaAsiHpiStream *stream );
-static PaError PaAsiHpi_StartStream( PaAsiHpiStream *stream, int outputPrimed );
-static PaError PaAsiHpi_StopStream( PaAsiHpiStream *stream, int abort );
-static PaError PaAsiHpi_ExplicitStop( PaAsiHpiStream *stream, int abort );
-static void PaAsiHpi_OnThreadExit( void *userData );
-static PaError PaAsiHpi_WaitForFrames( PaAsiHpiStream *stream, unsigned long *framesAvail,
-                                       PaStreamCallbackFlags *cbFlags );
-static void PaAsiHpi_CalculateTimeInfo( PaAsiHpiStream *stream, PaStreamCallbackTimeInfo *timeInfo );
-static PaError PaAsiHpi_BeginProcessing( PaAsiHpiStream* stream, unsigned long* numFrames,
-        PaStreamCallbackFlags *cbFlags );
-static PaError PaAsiHpi_EndProcessing( PaAsiHpiStream *stream, unsigned long numFrames,
-                                       PaStreamCallbackFlags *cbFlags );
-
-/* ==========================================================================
- * ============================= IMPLEMENTATION =============================
- * ========================================================================== */
-
-/* --------------------------- Host API Interface --------------------------- */
-
-/** Enumerate all PA devices (= HPI streams).
- This compiles a list of all HPI adapters, and registers a PA device for each input and
- output stream it finds. Most errors are ignored, as missing or erroneous devices are
- simply skipped.
-
- @param hpiHostApi Pointer to HPI host API struct
-
- @return PortAudio error code (only paInsufficientMemory in practice)
- */
-static PaError PaAsiHpi_BuildDeviceList( PaAsiHpiHostApiRepresentation *hpiHostApi )
-{
-    PaError result = paNoError;
-    PaUtilHostApiRepresentation *hostApi = &hpiHostApi->baseHostApiRep;
-    PaHostApiInfo *baseApiInfo = &hostApi->info;
-    PaAsiHpiDeviceInfo *hpiDeviceList;
-    HW16 adapterList[ HPI_MAX_ADAPTERS ];
-    HW16 numAdapters;
-    HW16 hpiError = 0;
-    int i, j, deviceCount = 0, deviceIndex = 0;
-
-    assert( hpiHostApi );
-    assert( hpiHostApi->subSys );
-
-    /* Look for adapters (not strictly necessary, as AdapterOpen can do the same, but this */
-    /* way we have less errors since we do not try to open adapters we know aren't there) */
-    /* Errors not considered critical here (subsystem may report 0 devices), but report them */
-    /* in debug mode. */
-    PA_ASIHPI_UNLESS_( HPI_SubSysFindAdapters( hpiHostApi->subSys, &numAdapters,
-                       adapterList, HPI_MAX_ADAPTERS ), paNoError );
-
-    /* First open and count the number of devices (= number of streams), to ease memory allocation */
-    for( i=0; i < HPI_MAX_ADAPTERS; ++i )
-    {
-        HW16 inStreams, outStreams;
-        HW16 version;
-        HW32 serial;
-        HW16 type;
-
-        /* If no adapter found at this index, skip it */
-        if( adapterList[i] == 0 )
-            continue;
-
-        /* Try to open adapter */
-        hpiError = HPI_AdapterOpen( hpiHostApi->subSys, i );
-        /* Report error and skip to next device on failure */
-        if( hpiError )
-        {
-            PA_ASIHPI_REPORT_ERROR_( hpiError );
-            continue;
-        }
-        hpiError = HPI_AdapterGetInfo( hpiHostApi->subSys, i,
-                                       &outStreams, &inStreams, &version, &serial, &type );
-        /* Skip to next device on failure */
-        if( hpiError )
-        {
-            PA_ASIHPI_REPORT_ERROR_( hpiError );
-            continue;
-        }
-        else
-        {
-            /* Assign default devices if available and increment device count */
-            if( (baseApiInfo->defaultInputDevice == paNoDevice) && (inStreams > 0) )
-                baseApiInfo->defaultInputDevice = deviceCount;
-            deviceCount += inStreams;
-            if( (baseApiInfo->defaultOutputDevice == paNoDevice) && (outStreams > 0) )
-                baseApiInfo->defaultOutputDevice = deviceCount;
-            deviceCount += outStreams;
-        }
-    }
-
-    /* Register any discovered devices */
-    if( deviceCount > 0 )
-    {
-        /* Memory allocation */
-        PA_UNLESS_( hostApi->deviceInfos = (PaDeviceInfo**) PaUtil_GroupAllocateMemory(
-                                               hpiHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount ),
-                    paInsufficientMemory );
-        /* Allocate all device info structs in a contiguous block */
-        PA_UNLESS_( hpiDeviceList = (PaAsiHpiDeviceInfo*) PaUtil_GroupAllocateMemory(
-                                        hpiHostApi->allocations, sizeof(PaAsiHpiDeviceInfo) * deviceCount ),
-                    paInsufficientMemory );
-
-        /* Now query devices again for information */
-        for( i=0; i < HPI_MAX_ADAPTERS; ++i )
-        {
-            HW16 inStreams, outStreams;
-            HW16 version;
-            HW32 serial;
-            HW16 type;
-
-            /* If no adapter found at this index, skip it */
-            if( adapterList[i] == 0 )
-                continue;
-
-            /* Assume adapter is still open from previous round */
-            hpiError = HPI_AdapterGetInfo( hpiHostApi->subSys, i,
-                                           &outStreams, &inStreams, &version, &serial, &type );
-            /* Report error and skip to next device on failure */
-            if( hpiError )
-            {
-                PA_ASIHPI_REPORT_ERROR_( hpiError );
-                continue;
-            }
-            else
-            {
-                PA_DEBUG(( "Found HPI Adapter ID=%4X Idx=%d #In=%d #Out=%d S/N=%d HWver=%c%d DSPver=%03d\n",
-                           type, i, inStreams, outStreams, serial,
-                           ((version>>3)&0xf)+'A',                  /* Hw version major */
-                           version&0x7,                             /* Hw version minor */
-                           ((version>>13)*100)+((version>>7)&0x3f)  /* DSP code version */
-                         ));
-            }
-
-            /* First add all input streams as devices */
-            for( j=0; j < inStreams; ++j )
-            {
-                PaAsiHpiDeviceInfo *hpiDevice = &hpiDeviceList[deviceIndex];
-                PaDeviceInfo *baseDeviceInfo = &hpiDevice->baseDeviceInfo;
-                char srcName[72];
-                char *deviceName;
-
-                memset( hpiDevice, 0, sizeof(PaAsiHpiDeviceInfo) );
-                /* Set implementation-specific device details */
-                hpiDevice->subSys = hpiHostApi->subSys;
-                hpiDevice->adapterIndex = i;
-                hpiDevice->adapterType = type;
-                hpiDevice->adapterVersion = version;
-                hpiDevice->adapterSerialNumber = serial;
-                hpiDevice->streamIndex = j;
-                hpiDevice->streamIsOutput = 0;
-                /* Set common PortAudio device stats */
-                baseDeviceInfo->structVersion = 2;
-                /* Make sure name string is owned by API info structure */
-                sprintf( srcName,
-                         "Adapter %d (%4X) - Input Stream %d", i+1, type, j+1 );
-                PA_UNLESS_( deviceName = (char *) PaUtil_GroupAllocateMemory(
-                                             hpiHostApi->allocations, strlen(srcName) + 1 ), paInsufficientMemory );
-                strcpy( deviceName, srcName );
-                baseDeviceInfo->name = deviceName;
-                baseDeviceInfo->hostApi = hpiHostApi->hostApiIndex;
-                baseDeviceInfo->maxInputChannels = HPI_MAX_CHANNELS;
-                baseDeviceInfo->maxOutputChannels = 0;
-                /* Default latency values for interactive performance */
-                baseDeviceInfo->defaultLowInputLatency = 0.01;
-                baseDeviceInfo->defaultLowOutputLatency = -1.0;
-                /* Default latency values for robust non-interactive applications (eg. playing sound files) */
-                baseDeviceInfo->defaultHighInputLatency = 0.2;
-                baseDeviceInfo->defaultHighOutputLatency = -1.0;
-                /* HPI interface can actually handle any sampling rate to 1 Hz accuracy,
-                * so this default is as good as any */
-                baseDeviceInfo->defaultSampleRate = 44100;
-
-                /* Store device in global PortAudio list */
-                hostApi->deviceInfos[deviceIndex++] = (PaDeviceInfo *) hpiDevice;
-            }
-
-            /* Now add all output streams as devices (I know, the repetition is painful) */
-            for( j=0; j < outStreams; ++j )
-            {
-                PaAsiHpiDeviceInfo *hpiDevice = &hpiDeviceList[deviceIndex];
-                PaDeviceInfo *baseDeviceInfo = &hpiDevice->baseDeviceInfo;
-                char srcName[72];
-                char *deviceName;
-
-                memset( hpiDevice, 0, sizeof(PaAsiHpiDeviceInfo) );
-                /* Set implementation-specific device details */
-                hpiDevice->subSys = hpiHostApi->subSys;
-                hpiDevice->adapterIndex = i;
-                hpiDevice->adapterType = type;
-                hpiDevice->adapterVersion = version;
-                hpiDevice->adapterSerialNumber = serial;
-                hpiDevice->streamIndex = j;
-                hpiDevice->streamIsOutput = 1;
-                /* Set common PortAudio device stats */
-                baseDeviceInfo->structVersion = 2;
-                /* Make sure name string is owned by API info structure */
-                sprintf( srcName,
-                         "Adapter %d (%4X) - Output Stream %d", i+1, type, j+1 );
-                PA_UNLESS_( deviceName = (char *) PaUtil_GroupAllocateMemory(
-                                             hpiHostApi->allocations, strlen(srcName) + 1 ), paInsufficientMemory );
-                strcpy( deviceName, srcName );
-                baseDeviceInfo->name = deviceName;
-                baseDeviceInfo->hostApi = hpiHostApi->hostApiIndex;
-                baseDeviceInfo->maxInputChannels = 0;
-                baseDeviceInfo->maxOutputChannels = HPI_MAX_CHANNELS;
-                /* Default latency values for interactive performance. */
-                baseDeviceInfo->defaultLowInputLatency = -1.0;
-                baseDeviceInfo->defaultLowOutputLatency = 0.01;
-                /* Default latency values for robust non-interactive applications (eg. playing sound files). */
-                baseDeviceInfo->defaultHighInputLatency = -1.0;
-                baseDeviceInfo->defaultHighOutputLatency = 0.2;
-                /* HPI interface can actually handle any sampling rate to 1 Hz accuracy,
-                * so this default is as good as any */
-                baseDeviceInfo->defaultSampleRate = 44100;
-
-                /* Store device in global PortAudio list */
-                hostApi->deviceInfos[deviceIndex++] = (PaDeviceInfo *) hpiDevice;
-            }
-        }
-    }
-
-    /* Finally acknowledge checked devices */
-    baseApiInfo->deviceCount = deviceIndex;
-
-error:
-    return result;
-}
-
-
-/** Initialize host API implementation.
- This is the only function exported beyond this file. It is called by PortAudio to initialize
- the host API. It stores API info, finds and registers all devices, and sets up callback and
- blocking interfaces.
-
- @param hostApi Pointer to host API struct
-
- @param hostApiIndex Index of current (HPI) host API
-
- @return PortAudio error code
- */
-PaError PaAsiHpi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
-{
-    PaError result = paNoError;
-    PaAsiHpiHostApiRepresentation *hpiHostApi = NULL;
-    PaHostApiInfo *baseApiInfo;
-
-    /* Allocate host API structure */
-    PA_UNLESS_( hpiHostApi = (PaAsiHpiHostApiRepresentation*) PaUtil_AllocateMemory(
-                                 sizeof(PaAsiHpiHostApiRepresentation) ), paInsufficientMemory );
-    PA_UNLESS_( hpiHostApi->allocations = PaUtil_CreateAllocationGroup(), paInsufficientMemory );
-
-    hpiHostApi->hostApiIndex = hostApiIndex;
-    hpiHostApi->subSys = NULL;
-
-    /* Try to initialize HPI subsystem */
-    if( ( hpiHostApi->subSys = HPI_SubSysCreate() ) == NULL)
-    {
-        /* the V19 development docs say that if an implementation
-         * detects that it cannot be used, it should return a NULL
-         * interface and paNoError */
-        PA_DEBUG(( "Could not open HPI interface\n" ));
-        result = paNoError;
-        *hostApi = NULL;
-        goto error;
-    }
-    else
-    {
-        HW32 hpiVersion;
-        PA_ASIHPI_UNLESS_( HPI_SubSysGetVersion( hpiHostApi->subSys, &hpiVersion ), paUnanticipatedHostError );
-        PA_DEBUG(( "HPI interface v%d.%02d\n",
-                   hpiVersion >> 8, 10*((hpiVersion & 0xF0) >> 4) + (hpiVersion & 0x0F) ));
-    }
-
-    *hostApi = &hpiHostApi->baseHostApiRep;
-    baseApiInfo = &((*hostApi)->info);
-    /* Fill in common API details */
-    baseApiInfo->structVersion = 1;
-    baseApiInfo->type = paAudioScienceHPI;
-    baseApiInfo->name = "AudioScience HPI";
-    baseApiInfo->deviceCount = 0;
-    baseApiInfo->defaultInputDevice = paNoDevice;
-    baseApiInfo->defaultOutputDevice = paNoDevice;
-
-    PA_ENSURE_( PaAsiHpi_BuildDeviceList( hpiHostApi ) );
-
-    (*hostApi)->Terminate = Terminate;
-    (*hostApi)->OpenStream = OpenStream;
-    (*hostApi)->IsFormatSupported = IsFormatSupported;
-
-    PaUtil_InitializeStreamInterface( &hpiHostApi->callbackStreamInterface, CloseStream, StartStream,
-                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
-                                      GetStreamTime, GetStreamCpuLoad,
-                                      PaUtil_DummyRead, PaUtil_DummyWrite,
-                                      PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
-
-    PaUtil_InitializeStreamInterface( &hpiHostApi->blockingStreamInterface, CloseStream, StartStream,
-                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
-                                      GetStreamTime, PaUtil_DummyGetCpuLoad,
-                                      ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
-
-    /* Store identity of main thread */
-    PA_ENSURE_( PaUnixThreading_Initialize() );
-
-    return result;
-error:
-    /* Clean up memory */
-    Terminate( (PaUtilHostApiRepresentation *)hpiHostApi );
-    return result;
-}
-
-
-/** Terminate host API implementation.
- This closes all HPI adapters and frees the HPI subsystem. It also frees the host API struct
- memory. It should be called once for every PaAsiHpi_Initialize call.
-
- @param Pointer to host API struct
- */
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
-{
-    PaAsiHpiHostApiRepresentation *hpiHostApi = (PaAsiHpiHostApiRepresentation*)hostApi;
-    int i;
-    PaError result = paNoError;
-
-    if( hpiHostApi )
-    {
-        /* Get rid of HPI-specific structures */
-        if( hpiHostApi->subSys )
-        {
-            HW16 lastAdapterIndex = HPI_MAX_ADAPTERS;
-            /* Iterate through device list and close adapters */
-            for( i=0; i < hostApi->info.deviceCount; ++i )
-            {
-                PaAsiHpiDeviceInfo *hpiDevice = (PaAsiHpiDeviceInfo *) hostApi->deviceInfos[ i ];
-                /* Close adapter only if it differs from previous one */
-                if( hpiDevice->adapterIndex != lastAdapterIndex )
-                {
-                    /* Ignore errors (report only during debugging) */
-                    PA_ASIHPI_UNLESS_( HPI_AdapterClose( hpiHostApi->subSys,
-                                                         hpiDevice->adapterIndex ), paNoError );
-                    lastAdapterIndex = hpiDevice->adapterIndex;
-                }
-            }
-            /* Finally dismantle HPI subsystem */
-            HPI_SubSysFree( hpiHostApi->subSys );
-        }
-
-        if( hpiHostApi->allocations )
-        {
-            PaUtil_FreeAllAllocations( hpiHostApi->allocations );
-            PaUtil_DestroyAllocationGroup( hpiHostApi->allocations );
-        }
-
-        PaUtil_FreeMemory( hpiHostApi );
-    }
-error:
-    return;
-}
-
-
-/** Converts PortAudio sample format to equivalent HPI format.
-
- @param paFormat PortAudio sample format
-
- @return HPI sample format
- */
-static HW16 PaAsiHpi_PaToHpiFormat( PaSampleFormat paFormat )
-{
-    /* Ignore interleaving flag */
-    switch( paFormat & ~paNonInterleaved )
-    {
-    case paFloat32:
-        return HPI_FORMAT_PCM32_FLOAT;
-
-    case paInt32:
-        return HPI_FORMAT_PCM32_SIGNED;
-
-    case paInt24:
-        return HPI_FORMAT_PCM24_SIGNED;
-
-    case paInt16:
-        return HPI_FORMAT_PCM16_SIGNED;
-
-    case paUInt8:
-        return HPI_FORMAT_PCM8_UNSIGNED;
-
-        /* Default is 16-bit signed */
-    case paInt8:
-    default:
-        return HPI_FORMAT_PCM16_SIGNED;
-    }
-}
-
-
-/** Converts HPI sample format to equivalent PortAudio format.
-
- @param paFormat HPI sample format
-
- @return PortAudio sample format
- */
-static PaSampleFormat PaAsiHpi_HpiToPaFormat( HW16 hpiFormat )
-{
-    switch( hpiFormat )
-    {
-    case HPI_FORMAT_PCM32_FLOAT:
-        return paFloat32;
-
-    case HPI_FORMAT_PCM32_SIGNED:
-        return paInt32;
-
-    case HPI_FORMAT_PCM24_SIGNED:
-        return paInt24;
-
-    case HPI_FORMAT_PCM16_SIGNED:
-        return paInt16;
-
-    case HPI_FORMAT_PCM8_UNSIGNED:
-        return paUInt8;
-
-        /* Default is custom format (e.g. for HPI MP3 format) */
-    default:
-        return paCustomFormat;
-    }
-}
-
-
-/** Creates HPI format struct based on PortAudio parameters.
- This also does some checks to see whether the desired format is valid, and whether
- the device allows it. This only checks the format of one half (input or output) of the
- PortAudio stream.
-
- @param hostApi Pointer to host API struct
-
- @param parameters Pointer to stream parameter struct
-
- @param sampleRate Desired sample rate
-
- @param hpiDevice Pointer to HPI device struct
-
- @param hpiFormat Resulting HPI format returned here
-
- @return PortAudio error code (typically indicating a problem with stream format)
- */
-static PaError PaAsiHpi_CreateFormat( struct PaUtilHostApiRepresentation *hostApi,
-                                      const PaStreamParameters *parameters, double sampleRate,
-                                      PaAsiHpiDeviceInfo **hpiDevice, HPI_FORMAT *hpiFormat )
-{
-    int maxChannelCount = 0;
-    PaSampleFormat hostSampleFormat = 0;
-    HW16 hpiError = 0;
-
-    /* Unless alternate device specification is supported, reject the use of
-       paUseHostApiSpecificDeviceSpecification */
-    if( parameters->device == paUseHostApiSpecificDeviceSpecification )
-        return paInvalidDevice;
-    else
-    {
-        assert( parameters->device < hostApi->info.deviceCount );
-        *hpiDevice = (PaAsiHpiDeviceInfo*) hostApi->deviceInfos[ parameters->device ];
-    }
-
-    /* Validate streamInfo - this implementation doesn't use custom stream info */
-    if( parameters->hostApiSpecificStreamInfo )
-        return paIncompatibleHostApiSpecificStreamInfo;
-
-    /* Check that device can support channel count */
-    if( (*hpiDevice)->streamIsOutput )
-    {
-        maxChannelCount = (*hpiDevice)->baseDeviceInfo.maxOutputChannels;
-    }
-    else
-    {
-        maxChannelCount = (*hpiDevice)->baseDeviceInfo.maxInputChannels;
-    }
-    if( (maxChannelCount == 0) || (parameters->channelCount > maxChannelCount) )
-        return paInvalidChannelCount;
-
-    /* All standard sample formats are supported by the buffer adapter,
-       and this implementation doesn't support any custom sample formats */
-    if( parameters->sampleFormat & paCustomFormat )
-        return paSampleFormatNotSupported;
-
-    /* Switch to closest HPI native format */
-    hostSampleFormat = PaUtil_SelectClosestAvailableFormat(PA_ASIHPI_AVAILABLE_FORMATS_,
-                       parameters->sampleFormat );
-    /* Setup format + info objects */
-    hpiError = HPI_FormatCreate( hpiFormat, (HW16)parameters->channelCount,
-                                 PaAsiHpi_PaToHpiFormat( hostSampleFormat ),
-                                 (HW32)sampleRate, 0, 0 );
-    if( hpiError )
-    {
-        PA_ASIHPI_REPORT_ERROR_( hpiError );
-        switch( hpiError )
-        {
-        case HPI_ERROR_INVALID_FORMAT:
-            return paSampleFormatNotSupported;
-
-        case HPI_ERROR_INVALID_SAMPLERATE:
-        case HPI_ERROR_INCOMPATIBLE_SAMPLERATE:
-            return paInvalidSampleRate;
-
-        case HPI_ERROR_INVALID_CHANNELS:
-            return paInvalidChannelCount;
-        }
-    }
-
-    return paNoError;
-}
-
-
-/** Open HPI input stream with given format.
- This attempts to open HPI input stream with desired format. If the format is not supported
- or the device is unavailable, the stream is closed and a PortAudio error code is returned.
-
- @param hostApi Pointer to host API struct
-
- @param hpiDevice Pointer to HPI device struct
-
- @param hpiFormat Pointer to HPI format struct
-
- @return PortAudio error code (typically indicating a problem with stream format or device)
-*/
-static PaError PaAsiHpi_OpenInput( struct PaUtilHostApiRepresentation *hostApi,
-                                   const PaAsiHpiDeviceInfo *hpiDevice, const HPI_FORMAT *hpiFormat,
-                                   HPI_HISTREAM *hpiStream )
-{
-    PaAsiHpiHostApiRepresentation *hpiHostApi = (PaAsiHpiHostApiRepresentation*)hostApi;
-    PaError result = paNoError;
-    HW16 hpiError = 0;
-
-    /* Catch misplaced output devices, as they typically have 0 input channels */
-    PA_UNLESS_( !hpiDevice->streamIsOutput, paInvalidChannelCount );
-    /* Try to open input stream */
-    PA_ASIHPI_UNLESS_( HPI_InStreamOpen( hpiHostApi->subSys, hpiDevice->adapterIndex,
-                                         hpiDevice->streamIndex, hpiStream ), paDeviceUnavailable );
-    /* Set input format (checking it in the process) */
-    /* Could also use HPI_InStreamQueryFormat, but this economizes the process */
-    hpiError = HPI_InStreamSetFormat( hpiHostApi->subSys, *hpiStream, (HPI_FORMAT*)hpiFormat );
-    if( hpiError )
-    {
-        PA_ASIHPI_REPORT_ERROR_( hpiError );
-        PA_ASIHPI_UNLESS_( HPI_InStreamClose( hpiHostApi->subSys, *hpiStream ), paNoError );
-        switch( hpiError )
-        {
-        case HPI_ERROR_INVALID_FORMAT:
-            return paSampleFormatNotSupported;
-
-        case HPI_ERROR_INVALID_SAMPLERATE:
-        case HPI_ERROR_INCOMPATIBLE_SAMPLERATE:
-            return paInvalidSampleRate;
-
-        case HPI_ERROR_INVALID_CHANNELS:
-            return paInvalidChannelCount;
-
-        default:
-            /* In case anything else went wrong */
-            return paInvalidDevice;
-        }
-    }
-
-error:
-    return result;
-}
-
-
-/** Open HPI output stream with given format.
- This attempts to open HPI output stream with desired format. If the format is not supported
- or the device is unavailable, the stream is closed and a PortAudio error code is returned.
-
- @param hostApi Pointer to host API struct
-
- @param hpiDevice Pointer to HPI device struct
-
- @param hpiFormat Pointer to HPI format struct
-
- @return PortAudio error code (typically indicating a problem with stream format or device)
-*/
-static PaError PaAsiHpi_OpenOutput( struct PaUtilHostApiRepresentation *hostApi,
-                                    const PaAsiHpiDeviceInfo *hpiDevice, const HPI_FORMAT *hpiFormat,
-                                    HPI_HOSTREAM *hpiStream )
-{
-    PaAsiHpiHostApiRepresentation *hpiHostApi = (PaAsiHpiHostApiRepresentation*)hostApi;
-    PaError result = paNoError;
-    HW16 hpiError = 0;
-
-    /* Catch misplaced input devices, as they typically have 0 output channels */
-    PA_UNLESS_( hpiDevice->streamIsOutput, paInvalidChannelCount );
-    /* Try to open output stream */
-    PA_ASIHPI_UNLESS_( HPI_OutStreamOpen( hpiHostApi->subSys, hpiDevice->adapterIndex,
-                                          hpiDevice->streamIndex, hpiStream ), paDeviceUnavailable );
-
-    /* Check output format (format is set on first write to output stream) */
-    hpiError = HPI_OutStreamQueryFormat( hpiHostApi->subSys, *hpiStream, (HPI_FORMAT*)hpiFormat );
-    if( hpiError )
-    {
-        PA_ASIHPI_REPORT_ERROR_( hpiError );
-        PA_ASIHPI_UNLESS_( HPI_OutStreamClose( hpiHostApi->subSys, *hpiStream ), paNoError );
-        switch( hpiError )
-        {
-        case HPI_ERROR_INVALID_FORMAT:
-            return paSampleFormatNotSupported;
-
-        case HPI_ERROR_INVALID_SAMPLERATE:
-        case HPI_ERROR_INCOMPATIBLE_SAMPLERATE:
-            return paInvalidSampleRate;
-
-        case HPI_ERROR_INVALID_CHANNELS:
-            return paInvalidChannelCount;
-
-        default:
-            /* In case anything else went wrong */
-            return paInvalidDevice;
-        }
-    }
-
-error:
-    return result;
-}
-
-
-/** Checks whether the desired stream formats and devices are supported
- (for both input and output).
- This is done by actually opening the appropriate HPI streams and closing them again.
-
- @param hostApi Pointer to host API struct
-
- @param inputParameters Pointer to stream parameter struct for input side of stream
-
- @param outputParameters Pointer to stream parameter struct for output side of stream
-
- @param sampleRate Desired sample rate
-
- @return PortAudio error code (paFormatIsSupported on success)
- */
-static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
-                                  const PaStreamParameters *inputParameters,
-                                  const PaStreamParameters *outputParameters,
-                                  double sampleRate )
-{
-    PaError result = paFormatIsSupported;
-    PaAsiHpiHostApiRepresentation *hpiHostApi = (PaAsiHpiHostApiRepresentation*)hostApi;
-    PaAsiHpiDeviceInfo *hpiDevice = NULL;
-    HPI_FORMAT hpiFormat;
-
-    /* Input stream */
-    if( inputParameters )
-    {
-        HPI_HISTREAM hpiStream;
-        PA_DEBUG(( "%s: Checking input params: dev=%d, sr=%d, chans=%d, fmt=%d\n",
-                   __FUNCTION__, inputParameters->device, (int)sampleRate,
-                   inputParameters->channelCount, inputParameters->sampleFormat ));
-        /* Create and validate format */
-        PA_ENSURE_( PaAsiHpi_CreateFormat( hostApi, inputParameters, sampleRate,
-                                           &hpiDevice, &hpiFormat ) );
-        /* Open stream to further check format */
-        PA_ENSURE_( PaAsiHpi_OpenInput( hostApi, hpiDevice, &hpiFormat, &hpiStream ) );
-        /* Close stream again */
-        PA_ASIHPI_UNLESS_( HPI_InStreamClose( hpiHostApi->subSys, hpiStream ), paNoError );
-    }
-
-    /* Output stream */
-    if( outputParameters )
-    {
-        HPI_HOSTREAM hpiStream;
-        PA_DEBUG(( "%s: Checking output params: dev=%d, sr=%d, chans=%d, fmt=%d\n",
-                   __FUNCTION__, outputParameters->device, (int)sampleRate,
-                   outputParameters->channelCount, outputParameters->sampleFormat ));
-        /* Create and validate format */
-        PA_ENSURE_( PaAsiHpi_CreateFormat( hostApi, outputParameters, sampleRate,
-                                           &hpiDevice, &hpiFormat ) );
-        /* Open stream to further check format */
-        PA_ENSURE_( PaAsiHpi_OpenOutput( hostApi, hpiDevice, &hpiFormat, &hpiStream ) );
-        /* Close stream again */
-        PA_ASIHPI_UNLESS_( HPI_OutStreamClose( hpiHostApi->subSys, hpiStream ), paNoError );
-    }
-
-error:
-    return result;
-}
-
-/* ---------------------------- Stream Interface ---------------------------- */
-
-/** Obtain HPI stream information.
- This obtains info such as stream state and available data/space in buffers. It also
- estimates whether an underflow or overflow occurred.
-
- @param streamComp Pointer to stream component (input or output) to query
-
- @param info Pointer to stream info struct that will contain result
-
- @return PortAudio error code (either paNoError, paDeviceUnavailable or paUnanticipatedHostError)
- */
-static PaError PaAsiHpi_GetStreamInfo( PaAsiHpiStreamComponent *streamComp, PaAsiHpiStreamInfo *info )
-{
-    PaError result = paDeviceUnavailable;
-    HW16 state;
-    HW32 bufferSize, dataSize, frameCounter, auxDataSize, threshold;
-    HW32 hwBufferSize, hwDataSize;
-
-    assert( streamComp );
-    assert( info );
-
-    /* First blank the stream info struct, in case something goes wrong below.
-       This saves the caller from initializing the struct. */
-    info->state = 0;
-    info->bufferSize = 0;
-    info->dataSize = 0;
-    info->frameCounter = 0;
-    info->auxDataSize = 0;
-    info->totalBufferedData = 0;
-    info->availableFrames = 0;
-    info->underflow = 0;
-    info->overflow = 0;
-
-    if( streamComp->hpiDevice && streamComp->hpiStream )
-    {
-        /* Obtain detailed stream info (either input or output) */
-        if( streamComp->hpiDevice->streamIsOutput )
-        {
-            PA_ASIHPI_UNLESS_( HPI_OutStreamGetInfoEx( streamComp->hpiDevice->subSys,
-                               streamComp->hpiStream,
-                               &state, &bufferSize, &dataSize, &frameCounter,
-                               &auxDataSize ), paUnanticipatedHostError );
-        }
-        else
-        {
-            PA_ASIHPI_UNLESS_( HPI_InStreamGetInfoEx( streamComp->hpiDevice->subSys,
-                               streamComp->hpiStream,
-                               &state, &bufferSize, &dataSize, &frameCounter,
-                               &auxDataSize ), paUnanticipatedHostError );
-        }
-        /* Load stream info */
-        info->state = state;
-        info->bufferSize = bufferSize;
-        info->dataSize = dataSize;
-        info->frameCounter = frameCounter;
-        info->auxDataSize = auxDataSize;
-        /* Determine total buffered data */
-        info->totalBufferedData = dataSize;
-        if( streamComp->hostBufferSize > 0 )
-            info->totalBufferedData += auxDataSize;
-        info->totalBufferedData /= streamComp->bytesPerFrame;
-        /* Determine immediately available frames */
-        info->availableFrames = streamComp->hpiDevice->streamIsOutput ?
-                                bufferSize - dataSize : dataSize;
-        info->availableFrames /= streamComp->bytesPerFrame;
-        /* Minimum space/data required in buffers */
-        threshold = PA_MIN( streamComp->tempBufferSize,
-                            streamComp->bytesPerFrame * PA_ASIHPI_MIN_FRAMES_ );
-        /* Obtain hardware buffer stats first, to simplify things */
-        hwBufferSize = streamComp->hardwareBufferSize;
-        hwDataSize = streamComp->hostBufferSize > 0 ? auxDataSize : dataSize;
-        /* Underflow is a bit tricky */
-        info->underflow = streamComp->hpiDevice->streamIsOutput ?
-                          /* Stream seems to start in drained state sometimes, so ignore initial underflow */
-                          (frameCounter > 0) && ( (state == HPI_STATE_DRAINED) || (hwDataSize == 0) ) :
-                          /* Input streams check the first-level (host) buffer for underflow */
-                          (state != HPI_STATE_STOPPED) && (dataSize < threshold);
-        /* Check for overflow in second-level (hardware) buffer for both input and output */
-        info->overflow = (state != HPI_STATE_STOPPED) && (hwBufferSize - hwDataSize < threshold);
-
-        return paNoError;
-    }
-
-error:
-    return result;
-}
-
-
-/** Display stream component information for debugging purposes.
-
- @param streamComp Pointer to stream component (input or output) to query
-
- @param stream Pointer to stream struct which contains the component above
- */
-static void PaAsiHpi_StreamComponentDump( PaAsiHpiStreamComponent *streamComp,
-        PaAsiHpiStream *stream )
-{
-    PaAsiHpiStreamInfo streamInfo;
-
-    assert( streamComp );
-    assert( stream );
-
-    /* Name of soundcard/device used by component */
-    PA_DEBUG(( "device: %s\n", streamComp->hpiDevice->baseDeviceInfo.name ));
-    /* Unfortunately some overlap between input and output here */
-    if( streamComp->hpiDevice->streamIsOutput )
-    {
-        /* Settings on the user side (as experienced by user callback) */
-        PA_DEBUG(( "user: %d-bit, %d ",
-                   8*stream->bufferProcessor.bytesPerUserOutputSample,
-                   stream->bufferProcessor.outputChannelCount));
-        if( stream->bufferProcessor.userOutputIsInterleaved )
-        {
-            PA_DEBUG(( "interleaved channels, " ));
-        }
-        else
-        {
-            PA_DEBUG(( "non-interleaved channels, " ));
-        }
-        PA_DEBUG(( "%d frames/buffer, latency = %5.1f ms\n",
-                   stream->bufferProcessor.framesPerUserBuffer,
-                   1000*stream->baseStreamRep.streamInfo.outputLatency ));
-        /* Settings on the host side (internal to PortAudio host API) */
-        PA_DEBUG(( "host: %d-bit, %d interleaved channels, %d frames/buffer ",
-                   8*stream->bufferProcessor.bytesPerHostOutputSample,
-                   stream->bufferProcessor.outputChannelCount,
-                   stream->bufferProcessor.framesPerHostBuffer ));
-    }
-    else
-    {
-        /* Settings on the user side (as experienced by user callback) */
-        PA_DEBUG(( "user: %d-bit, %d ",
-                   8*stream->bufferProcessor.bytesPerUserInputSample,
-                   stream->bufferProcessor.inputChannelCount));
-        if( stream->bufferProcessor.userInputIsInterleaved )
-        {
-            PA_DEBUG(( "interleaved channels, " ));
-        }
-        else
-        {
-            PA_DEBUG(( "non-interleaved channels, " ));
-        }
-        PA_DEBUG(( "%d frames/buffer, latency = %5.1f ms\n",
-                   stream->bufferProcessor.framesPerUserBuffer,
-                   1000*stream->baseStreamRep.streamInfo.inputLatency ));
-        /* Settings on the host side (internal to PortAudio host API) */
-        PA_DEBUG(( "host: %d-bit, %d interleaved channels, %d frames/buffer ",
-                   8*stream->bufferProcessor.bytesPerHostInputSample,
-                   stream->bufferProcessor.inputChannelCount,
-                   stream->bufferProcessor.framesPerHostBuffer ));
-    }
-    switch( stream->bufferProcessor.hostBufferSizeMode )
-    {
-    case paUtilFixedHostBufferSize:
-        PA_DEBUG(( "[fixed] " ));
-        break;
-    case paUtilBoundedHostBufferSize:
-        PA_DEBUG(( "[bounded] " ));
-        break;
-    case paUtilUnknownHostBufferSize:
-        PA_DEBUG(( "[unknown] " ));
-        break;
-    case paUtilVariableHostBufferSizePartialUsageAllowed:
-        PA_DEBUG(( "[variable] " ));
-        break;
-    }
-    PA_DEBUG(( "(%d max)\n", streamComp->tempBufferSize / streamComp->bytesPerFrame ));
-    /* HPI hardware settings */
-    PA_DEBUG(( "HPI: adapter %d stream %d, %d-bit, %d-channel, %d Hz\n",
-               streamComp->hpiDevice->adapterIndex, streamComp->hpiDevice->streamIndex,
-               8 * streamComp->bytesPerFrame / streamComp->hpiFormat.wChannels,
-               streamComp->hpiFormat.wChannels,
-               streamComp->hpiFormat.dwSampleRate ));
-    /* Stream state and buffer levels */
-    PA_DEBUG(( "HPI: " ));
-    PaAsiHpi_GetStreamInfo( streamComp, &streamInfo );
-    switch( streamInfo.state )
-    {
-    case HPI_STATE_STOPPED:
-        PA_DEBUG(( "[STOPPED] " ));
-        break;
-    case HPI_STATE_PLAYING:
-        PA_DEBUG(( "[PLAYING] " ));
-        break;
-    case HPI_STATE_RECORDING:
-        PA_DEBUG(( "[RECORDING] " ));
-        break;
-    case HPI_STATE_DRAINED:
-        PA_DEBUG(( "[DRAINED] " ));
-        break;
-    default:
-        PA_DEBUG(( "[unknown state] " ));
-        break;
-    }
-    if( streamComp->hostBufferSize )
-    {
-        PA_DEBUG(( "host = %d/%d B, ", streamInfo.dataSize, streamComp->hostBufferSize ));
-        PA_DEBUG(( "hw = %d/%d (%d) B, ", streamInfo.auxDataSize,
-                   streamComp->hardwareBufferSize, streamComp->outputBufferCap ));
-    }
-    else
-    {
-        PA_DEBUG(( "hw = %d/%d B, ", streamInfo.dataSize, streamComp->hardwareBufferSize ));
-    }
-    PA_DEBUG(( "count = %d", streamInfo.frameCounter ));
-    if( streamInfo.overflow )
-    {
-        PA_DEBUG(( " [overflow]" ));
-    }
-    else if( streamInfo.underflow )
-    {
-        PA_DEBUG(( " [underflow]" ));
-    }
-    PA_DEBUG(( "\n" ));
-}
-
-
-/** Display stream information for debugging purposes.
-
- @param stream Pointer to stream to query
- */
-static void PaAsiHpi_StreamDump( PaAsiHpiStream *stream )
-{
-    assert( stream );
-
-    PA_DEBUG(( "\n------------------------- STREAM INFO FOR %p ---------------------------\n", stream ));
-    /* General stream info (input+output) */
-    if( stream->baseStreamRep.streamCallback )
-    {
-        PA_DEBUG(( "[callback] " ));
-    }
-    else
-    {
-        PA_DEBUG(( "[blocking] " ));
-    }
-    PA_DEBUG(( "sr=%d Hz, poll=%d ms, max %d frames/buf ",
-               (int)stream->baseStreamRep.streamInfo.sampleRate,
-               stream->pollingInterval, stream->maxFramesPerHostBuffer ));
-    switch( stream->state )
-    {
-    case paAsiHpiStoppedState:
-        PA_DEBUG(( "[stopped]\n" ));
-        break;
-    case paAsiHpiActiveState:
-        PA_DEBUG(( "[active]\n" ));
-        break;
-    case paAsiHpiCallbackFinishedState:
-        PA_DEBUG(( "[cb fin]\n" ));
-        break;
-    default:
-        PA_DEBUG(( "[unknown state]\n" ));
-        break;
-    }
-    if( stream->callbackMode )
-    {
-        PA_DEBUG(( "cb info: thread=%p, cbAbort=%d, cbFinished=%d\n",
-                   stream->thread.thread, stream->callbackAbort, stream->callbackFinished ));
-    }
-
-    PA_DEBUG(( "----------------------------------- Input  ------------------------------------\n" ));
-    if( stream->input )
-    {
-        PaAsiHpi_StreamComponentDump( stream->input, stream );
-    }
-    else
-    {
-        PA_DEBUG(( "*none*\n" ));
-    }
-
-    PA_DEBUG(( "----------------------------------- Output ------------------------------------\n" ));
-    if( stream->output )
-    {
-        PaAsiHpi_StreamComponentDump( stream->output, stream );
-    }
-    else
-    {
-        PA_DEBUG(( "*none*\n" ));
-    }
-    PA_DEBUG(( "-------------------------------------------------------------------------------\n\n" ));
-
-}
-
-
-/** Determine buffer sizes and allocate appropriate stream buffers.
- This attempts to allocate a BBM (host) buffer for the HPI stream component (either input
- or output, as both have similar buffer needs). Not all AudioScience adapters support BBM,
- in which case the hardware buffer has to suffice. The size of the HPI host buffer is chosen
- as a multiple of framesPerPaHostBuffer, and also influenced by the suggested latency and the
- estimated minimum polling interval. The HPI host and hardware buffer sizes are stored, and an
- appropriate cap for the hardware buffer is also calculated. Finally, the temporary stream
- buffer which serves as the PortAudio host buffer for this implementation is allocated.
- This buffer contains an integer number of user buffers, to simplify buffer adaption in the
- buffer processor. The function returns paBufferTooBig if the HPI interface cannot allocate
- an HPI host buffer of the desired size.
-
- @param streamComp Pointer to stream component struct
-
- @param pollingInterval Polling interval for stream, in milliseconds
-
- @param framesPerPaHostBuffer Size of PortAudio host buffer, in frames
-
- @param suggestedLatency Suggested latency for stream component, in seconds
-
- @return PortAudio error code (possibly paBufferTooBig or paInsufficientMemory)
- */
-static PaError PaAsiHpi_SetupBuffers( PaAsiHpiStreamComponent *streamComp, HW32 pollingInterval,
-                                      unsigned long framesPerPaHostBuffer, PaTime suggestedLatency )
-{
-    PaError result = paNoError;
-    PaAsiHpiStreamInfo streamInfo;
-    unsigned long hpiBufferSize = 0, paHostBufferSize = 0;
-
-    assert( streamComp );
-    assert( streamComp->hpiDevice );
-
-    /* Obtain size of hardware buffer of HPI stream, since we will be activating BBM shortly
-       and afterwards the buffer size will refer to the BBM (host-side) buffer.
-       This is necessary to enable reliable detection of xruns. */
-    PA_ENSURE_( PaAsiHpi_GetStreamInfo( streamComp, &streamInfo ) );
-    streamComp->hardwareBufferSize = streamInfo.bufferSize;
-    hpiBufferSize = streamInfo.bufferSize;
-
-    /* Check if BBM (background bus mastering) is to be enabled */
-    if( PA_ASIHPI_USE_BBM_ )
-    {
-        HW32 bbmBufferSize = 0, preLatencyBufferSize = 0;
-        HW16 hpiError = 0;
-        PaTime pollingOverhead;
-
-        /* Check overhead of Pa_Sleep() call (minimum sleep duration in ms -> OS dependent) */
-        pollingOverhead = PaUtil_GetTime();
-        Pa_Sleep( 0 );
-        pollingOverhead = 1000*(PaUtil_GetTime() - pollingOverhead);
-        PA_DEBUG(( "polling overhead = %f ms (length of 0-second sleep)\n", pollingOverhead ));
-        /* Obtain minimum recommended size for host buffer (in bytes) */
-        PA_ASIHPI_UNLESS_( HPI_StreamEstimateBufferSize( &streamComp->hpiFormat,
-                           pollingInterval + (HW32)ceil( pollingOverhead ),
-                           &bbmBufferSize ), paUnanticipatedHostError );
-        /* BBM places more stringent requirements on buffer size (see description */
-        /* of HPI_StreamEstimateBufferSize in HPI API document) */
-        bbmBufferSize *= 3;
-        /* Make sure the BBM buffer contains multiple PA host buffers */
-        if( bbmBufferSize < 3 * streamComp->bytesPerFrame * framesPerPaHostBuffer )
-            bbmBufferSize = 3 * streamComp->bytesPerFrame * framesPerPaHostBuffer;
-        /* Try to honor latency suggested by user by growing buffer (no decrease possible) */
-        if( suggestedLatency > 0.0 )
-        {
-            PaTime bufferDuration = ((PaTime)bbmBufferSize) / streamComp->bytesPerFrame
-                                    / streamComp->hpiFormat.dwSampleRate;
-            /* Don't decrease buffer */
-            if( bufferDuration < suggestedLatency )
-            {
-                /* Save old buffer size, to be retried if new size proves too big */
-                preLatencyBufferSize = bbmBufferSize;
-                bbmBufferSize = (HW32)ceil( suggestedLatency * streamComp->bytesPerFrame
-                                            * streamComp->hpiFormat.dwSampleRate );
-            }
-        }
-        /* Choose closest memory block boundary (HPI API document states that
-        "a buffer size of Nx4096 - 20 makes the best use of memory"
-        (under the entry for HPI_StreamEstimateBufferSize)) */
-        bbmBufferSize = ((HW32)ceil((bbmBufferSize + 20)/4096.0))*4096 - 20;
-        streamComp->hostBufferSize = bbmBufferSize;
-        /* Allocate BBM host buffer (this enables bus mastering transfers in background) */
-        if( streamComp->hpiDevice->streamIsOutput )
-            hpiError = HPI_OutStreamHostBufferAllocate( streamComp->hpiDevice->subSys,
-                       streamComp->hpiStream,
-                       bbmBufferSize );
-        else
-            hpiError = HPI_InStreamHostBufferAllocate( streamComp->hpiDevice->subSys,
-                       streamComp->hpiStream,
-                       bbmBufferSize );
-        if( hpiError )
-        {
-            PA_ASIHPI_REPORT_ERROR_( hpiError );
-            /* Indicate that BBM is disabled */
-            streamComp->hostBufferSize = 0;
-            /* Retry with smaller buffer size (transfers will still work, but not via BBM) */
-            if( hpiError == HPI_ERROR_INVALID_DATASIZE )
-            {
-                /* Retry BBM allocation with smaller size if requested latency proved too big */
-                if( preLatencyBufferSize > 0 )
-                {
-                    PA_DEBUG(( "Retrying BBM allocation with smaller size (%d vs. %d bytes)\n",
-                               preLatencyBufferSize, bbmBufferSize ));
-                    bbmBufferSize = preLatencyBufferSize;
-                    if( streamComp->hpiDevice->streamIsOutput )
-                        hpiError = HPI_OutStreamHostBufferAllocate( streamComp->hpiDevice->subSys,
-                                   streamComp->hpiStream,
-                                   bbmBufferSize );
-                    else
-                        hpiError = HPI_InStreamHostBufferAllocate( streamComp->hpiDevice->subSys,
-                                   streamComp->hpiStream,
-                                   bbmBufferSize );
-                    /* Another round of error checking */
-                    if( hpiError )
-                    {
-                        PA_ASIHPI_REPORT_ERROR_( hpiError );
-                        /* No escapes this time */
-                        if( hpiError == HPI_ERROR_INVALID_DATASIZE )
-                        {
-                            result = paBufferTooBig;
-                            goto error;
-                        }
-                        else if( hpiError != HPI_ERROR_INVALID_OPERATION )
-                        {
-                            result = paUnanticipatedHostError;
-                            goto error;
-                        }
-                    }
-                    else
-                    {
-                        streamComp->hostBufferSize = bbmBufferSize;
-                        hpiBufferSize = bbmBufferSize;
-                    }
-                }
-                else
-                {
-                    result = paBufferTooBig;
-                    goto error;
-                }
-            }
-            /* If BBM not supported, foreground transfers will be used, but not a show-stopper */
-            /* Anything else is an error */
-            else if( hpiError != HPI_ERROR_INVALID_OPERATION )
-            {
-                result = paUnanticipatedHostError;
-                goto error;
-            }
-        }
-        else
-        {
-            hpiBufferSize = bbmBufferSize;
-        }
-    }
-
-    /* Final check of buffer size */
-    paHostBufferSize = streamComp->bytesPerFrame * framesPerPaHostBuffer;
-    if( hpiBufferSize < 3*paHostBufferSize )
-    {
-        result = paBufferTooBig;
-        goto error;
-    }
-    /* Set cap on output buffer size, based on latency suggestions */
-    if( streamComp->hpiDevice->streamIsOutput )
-    {
-        PaTime latency = suggestedLatency > 0.0 ? suggestedLatency :
-                         streamComp->hpiDevice->baseDeviceInfo.defaultHighOutputLatency;
-        streamComp->outputBufferCap =
-            (HW32)ceil( latency * streamComp->bytesPerFrame * streamComp->hpiFormat.dwSampleRate );
-        /* The cap should not be too small, to prevent underflow */
-        if( streamComp->outputBufferCap < 4*paHostBufferSize )
-            streamComp->outputBufferCap = 4*paHostBufferSize;
-    }
-    else
-    {
-        streamComp->outputBufferCap = 0;
-    }
-    /* Temp buffer size should be multiple of PA host buffer size (or 1x, if using fixed blocks) */
-    streamComp->tempBufferSize = paHostBufferSize;
-    /* Allocate temp buffer */
-    PA_UNLESS_( streamComp->tempBuffer = (HW8 *)PaUtil_AllocateMemory( streamComp->tempBufferSize ),
-                paInsufficientMemory );
-error:
-    return result;
-}
-
-
-/** Opens PortAudio stream.
- This determines a suitable value for framesPerBuffer, if the user didn't specify it,
- based on the suggested latency. It then opens each requested stream direction with the
- appropriate stream format, and allocates the required stream buffers. It sets up the
- various PortAudio structures dealing with streams, and estimates the stream latency.
-
- See pa_hostapi.h for a list of validity guarantees made about OpenStream parameters.
-
- @param hostApi Pointer to host API struct
-
- @param s List of open streams, where successfully opened stream will go
-
- @param inputParameters Pointer to stream parameter struct for input side of stream
-
- @param outputParameters Pointer to stream parameter struct for output side of stream
-
- @param sampleRate Desired sample rate
-
- @param framesPerBuffer Desired number of frames per buffer passed to user callback
-                        (or chunk size for blocking stream)
-
- @param streamFlags Stream flags
-
- @param streamCallback Pointer to user callback function (zero for blocking interface)
-
- @param userData Pointer to user data that will be passed to callback function along with data
-
- @return PortAudio error code
-*/
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
-                           PaStream **s,
-                           const PaStreamParameters *inputParameters,
-                           const PaStreamParameters *outputParameters,
-                           double sampleRate,
-                           unsigned long framesPerBuffer,
-                           PaStreamFlags streamFlags,
-                           PaStreamCallback *streamCallback,
-                           void *userData )
-{
-    PaError result = paNoError;
-    PaAsiHpiHostApiRepresentation *hpiHostApi = (PaAsiHpiHostApiRepresentation*)hostApi;
-    PaAsiHpiStream *stream = NULL;
-    unsigned long framesPerHostBuffer = framesPerBuffer;
-    int inputChannelCount = 0, outputChannelCount = 0;
-    PaSampleFormat inputSampleFormat = 0, outputSampleFormat = 0;
-    PaSampleFormat hostInputSampleFormat = 0, hostOutputSampleFormat = 0;
-    PaTime maxSuggestedLatency = 0.0;
-
-    /* Validate platform-specific flags -> none expected for HPI */
-    if( (streamFlags & paPlatformSpecificFlags) != 0 )
-        return paInvalidFlag; /* unexpected platform-specific flag */
-
-    /* Create blank stream structure */
-    PA_UNLESS_( stream = (PaAsiHpiStream *)PaUtil_AllocateMemory( sizeof(PaAsiHpiStream) ),
-                paInsufficientMemory );
-    memset( stream, 0, sizeof(PaAsiHpiStream) );
-
-    /* If the number of frames per buffer is unspecified, we have to come up with one. */
-    if( framesPerHostBuffer == paFramesPerBufferUnspecified )
-    {
-        if( inputParameters )
-            maxSuggestedLatency = inputParameters->suggestedLatency;
-        if( outputParameters && (outputParameters->suggestedLatency > maxSuggestedLatency) )
-            maxSuggestedLatency = outputParameters->suggestedLatency;
-        /* Use suggested latency if available */
-        if( maxSuggestedLatency > 0.0 )
-            framesPerHostBuffer = (unsigned long)ceil( maxSuggestedLatency * sampleRate );
-        else
-            /* AudioScience cards like BIG buffers by default */
-            framesPerHostBuffer = 4096;
-    }
-    /* Lower bounds on host buffer size, due to polling and HPI constraints */
-    if( 1000.0*framesPerHostBuffer/sampleRate < PA_ASIHPI_MIN_POLLING_INTERVAL_ )
-        framesPerHostBuffer = (unsigned long)ceil( sampleRate * PA_ASIHPI_MIN_POLLING_INTERVAL_ / 1000.0 );
-    /*    if( framesPerHostBuffer < PA_ASIHPI_MIN_FRAMES_ )
-            framesPerHostBuffer = PA_ASIHPI_MIN_FRAMES_; */
-    /* Efficient if host buffer size is integer multiple of user buffer size */
-    if( framesPerBuffer > 0 )
-        framesPerHostBuffer = (unsigned long)ceil( (double)framesPerHostBuffer / framesPerBuffer ) * framesPerBuffer;
-    /* Buffer should always be a multiple of 4 bytes to facilitate 32-bit PCI transfers.
-     By keeping the frames a multiple of 4, this is ensured even for 8-bit mono sound. */
-    framesPerHostBuffer = (framesPerHostBuffer / 4) * 4;
-    /* Polling is based on time length (in milliseconds) of user-requested block size */
-    stream->pollingInterval = (HW32)ceil( 1000.0*framesPerHostBuffer/sampleRate );
-    assert( framesPerHostBuffer > 0 );
-
-    /* Open underlying streams, check formats and allocate buffers */
-    if( inputParameters )
-    {
-        /* Create blank stream component structure */
-        PA_UNLESS_( stream->input = (PaAsiHpiStreamComponent *)PaUtil_AllocateMemory( sizeof(PaAsiHpiStreamComponent) ),
-                    paInsufficientMemory );
-        memset( stream->input, 0, sizeof(PaAsiHpiStreamComponent) );
-        /* Create/validate format */
-        PA_ENSURE_( PaAsiHpi_CreateFormat( hostApi, inputParameters, sampleRate,
-                                           &stream->input->hpiDevice, &stream->input->hpiFormat ) );
-        /* Open stream and set format */
-        PA_ENSURE_( PaAsiHpi_OpenInput( hostApi, stream->input->hpiDevice, &stream->input->hpiFormat,
-                                        &stream->input->hpiStream ) );
-        inputChannelCount = inputParameters->channelCount;
-        inputSampleFormat = inputParameters->sampleFormat;
-        hostInputSampleFormat = PaAsiHpi_HpiToPaFormat( stream->input->hpiFormat.wFormat );
-        stream->input->bytesPerFrame = inputChannelCount * Pa_GetSampleSize( hostInputSampleFormat );
-        assert( stream->input->bytesPerFrame > 0 );
-        /* Allocate host and temp buffers of appropriate size */
-        PA_ENSURE_( PaAsiHpi_SetupBuffers( stream->input, stream->pollingInterval,
-                                           framesPerHostBuffer, inputParameters->suggestedLatency ) );
-    }
-    if( outputParameters )
-    {
-        /* Create blank stream component structure */
-        PA_UNLESS_( stream->output = (PaAsiHpiStreamComponent *)PaUtil_AllocateMemory( sizeof(PaAsiHpiStreamComponent) ),
-                    paInsufficientMemory );
-        memset( stream->output, 0, sizeof(PaAsiHpiStreamComponent) );
-        /* Create/validate format */
-        PA_ENSURE_( PaAsiHpi_CreateFormat( hostApi, outputParameters, sampleRate,
-                                           &stream->output->hpiDevice, &stream->output->hpiFormat ) );
-        /* Open stream and check format */
-        PA_ENSURE_( PaAsiHpi_OpenOutput( hostApi, stream->output->hpiDevice,
-                                         &stream->output->hpiFormat,
-                                         &stream->output->hpiStream ) );
-        outputChannelCount = outputParameters->channelCount;
-        outputSampleFormat = outputParameters->sampleFormat;
-        hostOutputSampleFormat = PaAsiHpi_HpiToPaFormat( stream->output->hpiFormat.wFormat );
-        stream->output->bytesPerFrame = outputChannelCount * Pa_GetSampleSize( hostOutputSampleFormat );
-        /* Allocate host and temp buffers of appropriate size */
-        PA_ENSURE_( PaAsiHpi_SetupBuffers( stream->output, stream->pollingInterval,
-                                           framesPerHostBuffer, outputParameters->suggestedLatency ) );
-    }
-
-    /* Determine maximum frames per host buffer (least common denominator of input/output) */
-    if( inputParameters && outputParameters )
-    {
-        stream->maxFramesPerHostBuffer = PA_MIN( stream->input->tempBufferSize / stream->input->bytesPerFrame,
-                                         stream->output->tempBufferSize / stream->output->bytesPerFrame );
-    }
-    else
-    {
-        stream->maxFramesPerHostBuffer = inputParameters ? stream->input->tempBufferSize / stream->input->bytesPerFrame
-                                         : stream->output->tempBufferSize / stream->output->bytesPerFrame;
-    }
-    assert( stream->maxFramesPerHostBuffer > 0 );
-    /* Initialize various other stream parameters */
-    stream->neverDropInput = streamFlags & paNeverDropInput;
-    stream->state = paAsiHpiStoppedState;
-
-    /* Initialize either callback or blocking interface */
-    if( streamCallback )
-    {
-        PaUtil_InitializeStreamRepresentation( &stream->baseStreamRep,
-                                               &hpiHostApi->callbackStreamInterface,
-                                               streamCallback, userData );
-        stream->callbackMode = 1;
-    }
-    else
-    {
-        PaUtil_InitializeStreamRepresentation( &stream->baseStreamRep,
-                                               &hpiHostApi->blockingStreamInterface,
-                                               streamCallback, userData );
-        /* Pre-allocate non-interleaved user buffer pointers for blocking interface */
-        PA_UNLESS_( stream->blockingUserBufferCopy =
-                        PaUtil_AllocateMemory( sizeof(void *) * PA_MAX( inputChannelCount, outputChannelCount ) ),
-                    paInsufficientMemory );
-        stream->callbackMode = 0;
-    }
-    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
-
-    /* Following pa_linux_alsa's lead, we operate with fixed host buffer size by default, */
-    /* since other modes will invariably lead to block adaption (maybe Bounded better?) */
-    PA_ENSURE_( PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
-                inputChannelCount, inputSampleFormat, hostInputSampleFormat,
-                outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
-                sampleRate, streamFlags,
-                framesPerBuffer, framesPerHostBuffer, paUtilFixedHostBufferSize,
-                streamCallback, userData ) );
-
-    stream->baseStreamRep.streamInfo.structVersion = 1;
-    stream->baseStreamRep.streamInfo.sampleRate = sampleRate;
-    /* Determine input latency from buffer processor and buffer sizes */
-    if( stream->input )
-    {
-        PaTime bufferDuration = ( stream->input->hostBufferSize + stream->input->hardwareBufferSize )
-                                / sampleRate / stream->input->bytesPerFrame;
-        stream->baseStreamRep.streamInfo.inputLatency =
-            PaUtil_GetBufferProcessorInputLatency( &stream->bufferProcessor ) +
-            bufferDuration - stream->maxFramesPerHostBuffer / sampleRate;
-        assert( stream->baseStreamRep.streamInfo.inputLatency > 0.0 );
-    }
-    /* Determine output latency from buffer processor and buffer sizes */
-    if( stream->output )
-    {
-        PaTime bufferDuration = ( stream->output->hostBufferSize + stream->output->hardwareBufferSize )
-                                / sampleRate / stream->output->bytesPerFrame;
-        /* Take buffer size cap into account (see PaAsiHpi_WaitForFrames) */
-        if( !stream->input && (stream->output->outputBufferCap > 0) )
-        {
-            bufferDuration = PA_MIN( bufferDuration,
-                                     stream->output->outputBufferCap / sampleRate / stream->output->bytesPerFrame );
-        }
-        stream->baseStreamRep.streamInfo.outputLatency =
-            PaUtil_GetBufferProcessorOutputLatency( &stream->bufferProcessor ) +
-            bufferDuration - stream->maxFramesPerHostBuffer / sampleRate;
-        assert( stream->baseStreamRep.streamInfo.outputLatency > 0.0 );
-    }
-
-    /* Report stream info, for debugging purposes */
-    PaAsiHpi_StreamDump( stream );
-
-    /* Save initialized stream to PA stream list */
-    *s = (PaStream*)stream;
-    return result;
-
-error:
-    CloseStream( (PaStream*)stream );
-    return result;
-}
-
-
-/** Close PortAudio stream.
- When CloseStream() is called, the multi-api layer ensures that the stream has already
- been stopped or aborted. This closes the underlying HPI streams and deallocates stream
- buffers and structs.
-
- @param s Pointer to PortAudio stream
-
- @return PortAudio error code
-*/
-static PaError CloseStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-
-    /* If stream is already gone, all is well */
-    if( stream == NULL )
-        return paNoError;
-
-    /* Generic stream cleanup */
-    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
-    PaUtil_TerminateStreamRepresentation( &stream->baseStreamRep );
-
-    /* Implementation-specific details - close internal streams */
-    if( stream->input )
-    {
-        /* Close HPI stream (freeing BBM host buffer in the process, if used) */
-        if( stream->input->hpiStream )
-        {
-            PA_ASIHPI_UNLESS_( HPI_InStreamClose( stream->input->hpiDevice->subSys,
-                                                  stream->input->hpiStream ), paUnanticipatedHostError );
-        }
-        /* Free temp buffer and stream component */
-        PaUtil_FreeMemory( stream->input->tempBuffer );
-        PaUtil_FreeMemory( stream->input );
-    }
-    if( stream->output )
-    {
-        /* Close HPI stream (freeing BBM host buffer in the process, if used) */
-        if( stream->output->hpiStream )
-        {
-            PA_ASIHPI_UNLESS_( HPI_OutStreamClose( stream->output->hpiDevice->subSys,
-                                                   stream->output->hpiStream ), paUnanticipatedHostError );
-        }
-        /* Free temp buffer and stream component */
-        PaUtil_FreeMemory( stream->output->tempBuffer );
-        PaUtil_FreeMemory( stream->output );
-    }
-
-    PaUtil_FreeMemory( stream->blockingUserBufferCopy );
-    PaUtil_FreeMemory( stream );
-
-error:
-    return result;
-}
-
-
-/** Prime HPI output stream with silence.
- This resets the output stream and uses PortAudio helper routines to fill the
- temp buffer with silence. It then writes two host buffers to the stream. This is supposed
- to be called before the stream is started. It has no effect on input-only streams.
-
- @param stream Pointer to stream struct
-
- @return PortAudio error code
- */
-static PaError PaAsiHpi_PrimeOutputWithSilence( PaAsiHpiStream *stream )
-{
-    PaError result = paNoError;
-    PaAsiHpiStreamComponent *out;
-    PaUtilZeroer *zeroer;
-    PaSampleFormat outputFormat;
-    HPI_DATA data;
-
-    assert( stream );
-    out = stream->output;
-    /* Only continue if stream has output channels */
-    if( !out )
-        return result;
-    assert( out->tempBuffer );
-
-    /* Clear all existing data in hardware playback buffer */
-    PA_ASIHPI_UNLESS_( HPI_OutStreamReset( out->hpiDevice->subSys,
-                                           out->hpiStream ), paUnanticipatedHostError );
-    /* Fill temp buffer with silence */
-    outputFormat = PaAsiHpi_HpiToPaFormat( out->hpiFormat.wFormat );
-    zeroer = PaUtil_SelectZeroer( outputFormat );
-    zeroer(out->tempBuffer, 1, out->tempBufferSize / Pa_GetSampleSize(outputFormat) );
-    /* Write temp buffer to hardware fifo twice, to get started */
-    PA_ASIHPI_UNLESS_( HPI_DataCreate( &data, &out->hpiFormat, out->tempBuffer, out->tempBufferSize ),
-                       paUnanticipatedHostError );
-    PA_ASIHPI_UNLESS_( HPI_OutStreamWrite( out->hpiDevice->subSys,
-                                           out->hpiStream, &data ), paUnanticipatedHostError );
-    PA_ASIHPI_UNLESS_( HPI_OutStreamWrite( out->hpiDevice->subSys,
-                                           out->hpiStream, &data ), paUnanticipatedHostError );
-
-error:
-    return result;
-}
-
-
-/** Start HPI streams (both input + output).
- This starts all HPI streams in the PortAudio stream. Output streams are first primed with
- silence, if required. After this call the PA stream is in the Active state.
-
- @todo Implement priming via the user callback
-
- @param stream Pointer to stream struct
-
- @param outputPrimed True if output is already primed (if false, silence will be loaded before starting)
-
- @return PortAudio error code
- */
-static PaError PaAsiHpi_StartStream( PaAsiHpiStream *stream, int outputPrimed )
-{
-    PaError result = paNoError;
-
-    if( stream->input )
-    {
-        PA_ASIHPI_UNLESS_( HPI_InStreamStart( stream->input->hpiDevice->subSys,
-                                              stream->input->hpiStream ), paUnanticipatedHostError );
-    }
-    if( stream->output )
-    {
-        if( !outputPrimed )
-        {
-            /* Buffer isn't primed, so load stream with silence */
-            PA_ENSURE_( PaAsiHpi_PrimeOutputWithSilence( stream ) );
-        }
-        PA_ASIHPI_UNLESS_( HPI_OutStreamStart( stream->output->hpiDevice->subSys,
-                                               stream->output->hpiStream ), paUnanticipatedHostError );
-    }
-    stream->state = paAsiHpiActiveState;
-    stream->callbackFinished = 0;
-
-    /* Report stream info for debugging purposes */
-    /*    PaAsiHpi_StreamDump( stream );   */
-
-error:
-    return result;
-}
-
-
-/** Start PortAudio stream.
- If the stream has a callback interface, this starts a helper thread to feed the user callback.
- The thread will then take care of starting the HPI streams, and this function will block
- until the streams actually start. In the case of a blocking interface, the HPI streams
- are simply started.
-
- @param s Pointer to PortAudio stream
-
- @return PortAudio error code
-*/
-static PaError StartStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-
-    assert( stream );
-
-    /* Ready the processor */
-    PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
-
-    if( stream->callbackMode )
-    {
-        /* Create and start callback engine thread */
-        /* Also waits 1 second for stream to be started by engine thread (otherwise aborts) */
-        PA_ENSURE_( PaUnixThread_New( &stream->thread, &CallbackThreadFunc, stream, 1., 0 ) );
-    }
-    else
-    {
-        PA_ENSURE_( PaAsiHpi_StartStream( stream, 0 ) );
-    }
-
-error:
-    return result;
-}
-
-
-/** Stop HPI streams (input + output), either softly or abruptly.
- If abort is false, the function blocks until the output stream is drained, otherwise it
- stops immediately and discards data in the stream hardware buffers.
-
- This function is safe to call from the callback engine thread as well as the main thread.
-
- @param stream Pointer to stream struct
-
- @param abort True if samples in output buffer should be discarded (otherwise blocks until stream is done)
-
- @return PortAudio error code
-
- */
-static PaError PaAsiHpi_StopStream( PaAsiHpiStream *stream, int abort )
-{
-    PaError result = paNoError;
-
-    assert( stream );
-
-    /* Input channels */
-    if( stream->input )
-    {
-        PA_ASIHPI_UNLESS_( HPI_InStreamReset( stream->input->hpiDevice->subSys,
-                                              stream->input->hpiStream ), paUnanticipatedHostError );
-    }
-    /* Output channels */
-    if( stream->output )
-    {
-        if( !abort )
-        {
-            /* Wait until HPI output stream is drained */
-            while( 1 )
-            {
-                PaAsiHpiStreamInfo streamInfo;
-                PaTime timeLeft;
-
-                /* Obtain number of samples waiting to be played */
-                PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->output, &streamInfo ) );
-                /* Check if stream is drained */
-                if( (streamInfo.state != HPI_STATE_PLAYING) &&
-                        (streamInfo.dataSize < stream->output->bytesPerFrame * PA_ASIHPI_MIN_FRAMES_) )
-                    break;
-                /* Sleep amount of time represented by remaining samples */
-                timeLeft = 1000.0 * streamInfo.dataSize / stream->output->bytesPerFrame
-                           / stream->baseStreamRep.streamInfo.sampleRate;
-                Pa_Sleep( (long)ceil( timeLeft ) );
-            }
-        }
-        PA_ASIHPI_UNLESS_( HPI_OutStreamReset( stream->output->hpiDevice->subSys,
-                                               stream->output->hpiStream ), paUnanticipatedHostError );
-    }
-
-    /* Report stream info for debugging purposes */
-    /*    PaAsiHpi_StreamDump( stream ); */
-
-error:
-    return result;
-}
-
-
-/** Stop or abort PortAudio stream.
-
- This function is used to explicitly stop the PortAudio stream (via StopStream/AbortStream),
- as opposed to the situation when the callback finishes with a result other than paContinue.
- If a stream is in callback mode we will have to inspect whether the background thread has
- finished, or we will have to take it out. In either case we join the thread before returning.
- In blocking mode, we simply tell HPI to stop abruptly (abort) or finish buffers (drain).
- The PortAudio stream will be in the Stopped state after a call to this function.
-
- Don't call this from the callback engine thread!
-
- @param stream Pointer to stream struct
-
- @param abort True if samples in output buffer should be discarded (otherwise blocks until stream is done)
-
- @return PortAudio error code
-*/
-static PaError PaAsiHpi_ExplicitStop( PaAsiHpiStream *stream, int abort )
-{
-    PaError result = paNoError;
-
-    /* First deal with the callback thread, cancelling and/or joining it if necessary */
-    if( stream->callbackMode )
-    {
-        PaError threadRes;
-        stream->callbackAbort = abort;
-        if( abort )
-        {
-            PA_DEBUG(( "Aborting callback\n" ));
-        }
-        else
-        {
-            PA_DEBUG(( "Stopping callback\n" ));
-        }
-        PA_ENSURE_( PaUnixThread_Terminate( &stream->thread, !abort, &threadRes ) );
-        if( threadRes != paNoError )
-        {
-            PA_DEBUG(( "Callback thread returned: %d\n", threadRes ));
-        }
-    }
-    else
-    {
-        PA_ENSURE_( PaAsiHpi_StopStream( stream, abort ) );
-    }
-
-    stream->state = paAsiHpiStoppedState;
-
-error:
-    return result;
-}
-
-
-/** Stop PortAudio stream.
- This blocks until the output buffers are drained.
-
- @param s Pointer to PortAudio stream
-
- @return PortAudio error code
-*/
-static PaError StopStream( PaStream *s )
-{
-    return PaAsiHpi_ExplicitStop( (PaAsiHpiStream *) s, 0 );
-}
-
-
-/** Abort PortAudio stream.
- This discards any existing data in output buffers and stops the stream immediately.
-
- @param s Pointer to PortAudio stream
-
- @return PortAudio error code
-*/
-static PaError AbortStream( PaStream *s )
-{
-    return PaAsiHpi_ExplicitStop( (PaAsiHpiStream * ) s, 1 );
-}
-
-
-/** Determine whether the stream is stopped.
- A stream is considered to be stopped prior to a successful call to StartStream and after
- a successful call to StopStream or AbortStream. If a stream callback returns a value other
- than paContinue the stream is NOT considered to be stopped (it is in CallbackFinished state).
-
- @param s Pointer to PortAudio stream
-
- @return Returns one (1) when the stream is stopped, zero (0) when the stream is running, or
-         a PaErrorCode (which are always negative) if PortAudio is not initialized or an
-         error is encountered.
-*/
-static PaError IsStreamStopped( PaStream *s )
-{
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-
-    assert( stream );
-    return stream->state == paAsiHpiStoppedState ? 1 : 0;
-}
-
-
-/** Determine whether the stream is active.
- A stream is active after a successful call to StartStream(), until it becomes inactive either
- as a result of a call to StopStream() or AbortStream(), or as a result of a return value
- other than paContinue from the stream callback. In the latter case, the stream is considered
- inactive after the last buffer has finished playing.
-
- @param s Pointer to PortAudio stream
-
- @return Returns one (1) when the stream is active (i.e. playing or recording audio),
-         zero (0) when not playing, or a PaErrorCode (which are always negative)
-         if PortAudio is not initialized or an error is encountered.
-*/
-static PaError IsStreamActive( PaStream *s )
-{
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-
-    assert( stream );
-    return stream->state == paAsiHpiActiveState ? 1 : 0;
-}
-
-
-/** Returns current stream time.
- This corresponds to the system clock. The clock should run continuously while the stream
- is open, i.e. between calls to OpenStream() and CloseStream(), therefore a frame counter
- is not good enough.
-
- @param s Pointer to PortAudio stream
-
- @return Stream time, in seconds
- */
-static PaTime GetStreamTime( PaStream *s )
-{
-    return PaUtil_GetTime();
-}
-
-
-/** Returns CPU load.
-
- @param s Pointer to PortAudio stream
-
- @return CPU load (0.0 if blocking interface is used)
- */
-static double GetStreamCpuLoad( PaStream *s )
-{
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-
-    return stream->callbackMode ? PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer ) : 0.0;
-}
-
-/* --------------------------- Callback Interface --------------------------- */
-
-/** Exit routine which is called when callback thread quits.
- This takes care of stopping the HPI streams (either waiting for output to finish, or
- abruptly). It also calls the user-supplied StreamFinished callback, and sets the
- stream state to CallbackFinished if it was reached via a non-paContinue return from
- the user callback function.
-
- @param userData A pointer to an open stream previously created with Pa_OpenStream
- */
-static void PaAsiHpi_OnThreadExit( void *userData )
-{
-    PaAsiHpiStream *stream = (PaAsiHpiStream *) userData;
-
-    assert( stream );
-
-    PaUtil_ResetCpuLoadMeasurer( &stream->cpuLoadMeasurer );
-
-    PA_DEBUG(( "%s: Stopping HPI streams\n", __FUNCTION__ ));
-    PaAsiHpi_StopStream( stream, stream->callbackAbort );
-    PA_DEBUG(( "%s: Stoppage\n", __FUNCTION__ ));
-
-    /* Eventually notify user all buffers have played */
-    if( stream->baseStreamRep.streamFinishedCallback )
-    {
-        stream->baseStreamRep.streamFinishedCallback( stream->baseStreamRep.userData );
-    }
-
-    /* Unfortunately both explicit calls to Stop/AbortStream (leading to Stopped state)
-     and implicit stops via paComplete/paAbort (leading to CallbackFinished state)
-     end up here - need another flag to remind us which is the case */
-    if( stream->callbackFinished )
-        stream->state = paAsiHpiCallbackFinishedState;
-}
-
-
-/** Wait until there is enough frames to fill a host buffer.
- The routine attempts to sleep until at least a full host buffer can be retrieved from the
- input HPI stream and passed to the output HPI stream. It will first sleep until enough
- output space is available, as this is usually easily achievable. If it is an output-only
- stream, it will also sleep if the hardware buffer is too full, thereby throttling the
- filling of the output buffer and reducing output latency. The routine then blocks until
- enough input samples are available, unless this will cause an output underflow. In the
- process, input overflows and output underflows are indicated.
-
- @param stream Pointer to stream struct
-
- @param framesAvail Returns the number of available frames
-
- @param cbFlags Overflows and underflows indicated in here
-
- @return PortAudio error code (only paUnanticipatedHostError expected)
- */
-static PaError PaAsiHpi_WaitForFrames( PaAsiHpiStream *stream, unsigned long *framesAvail,
-                                       PaStreamCallbackFlags *cbFlags )
-{
-    PaError result = paNoError;
-    double sampleRate;
-    unsigned long framesTarget;
-    HW32 outputData = 0, outputSpace = 0, inputData = 0, framesLeft = 0;
-
-    assert( stream );
-    assert( stream->input || stream->output );
-
-    sampleRate = stream->baseStreamRep.streamInfo.sampleRate;
-    /* We have to come up with this much frames on both input and output */
-    framesTarget = stream->bufferProcessor.framesPerHostBuffer;
-    assert( framesTarget > 0 );
-
-    while( 1 )
-    {
-        PaAsiHpiStreamInfo info;
-        /* Check output first, as this takes priority in the default full-duplex mode */
-        if( stream->output )
-        {
-            PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->output, &info ) );
-            /* Wait until enough space is available in output buffer to receive a full block */
-            if( info.availableFrames < framesTarget )
-            {
-                framesLeft = framesTarget - info.availableFrames;
-                Pa_Sleep( (long)ceil( 1000 * framesLeft / sampleRate ) );
-                continue;
-            }
-            /* Wait until the data in hardware buffer has dropped to a sensible level.
-             Without this, the hardware buffer quickly fills up in the absence of an input
-             stream to regulate its data rate (if data generation is fast). This leads to
-             large latencies, as the AudioScience hardware buffers are humongous.
-             This is similar to the default "Hardware Buffering=off" option in the
-             AudioScience WAV driver. */
-            if( !stream->input && (stream->output->outputBufferCap > 0) &&
-                    ( info.totalBufferedData > stream->output->outputBufferCap / stream->output->bytesPerFrame ) )
-            {
-                framesLeft = info.totalBufferedData - stream->output->outputBufferCap / stream->output->bytesPerFrame;
-                Pa_Sleep( (long)ceil( 1000 * framesLeft / sampleRate ) );
-                continue;
-            }
-            outputData = info.totalBufferedData;
-            outputSpace = info.availableFrames;
-            /* Report output underflow to callback */
-            if( info.underflow )
-            {
-                *cbFlags |= paOutputUnderflow;
-            }
-        }
-
-        /* Now check input side */
-        if( stream->input )
-        {
-            PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->input, &info ) );
-            /* If a full block of samples hasn't been recorded yet, wait for it if possible */
-            if( info.availableFrames < framesTarget )
-            {
-                framesLeft = framesTarget - info.availableFrames;
-                /* As long as output is not disrupted in the process, wait for a full
-                block of input samples */
-                if( !stream->output || (outputData > framesLeft) )
-                {
-                    Pa_Sleep( (long)ceil( 1000 * framesLeft / sampleRate ) );
-                    continue;
-                }
-            }
-            inputData = info.availableFrames;
-            /** @todo The paInputOverflow flag should be set in the callback containing the
-             first input sample following the overflow. That means the block currently sitting
-             at the fore-front of recording, i.e. typically the one containing the newest (last)
-             sample in the HPI buffer system. This is most likely not the same as the current
-             block of data being passed to the callback. The current overflow should ideally
-             be noted in an overflow list of sorts, with an indication of when it should be
-             reported. The trouble starts if there are several separate overflow incidents,
-             given a big input buffer. Oh well, something to try out later... */
-            if( info.overflow )
-            {
-                *cbFlags |= paInputOverflow;
-            }
-        }
-        break;
-    }
-    /* Full-duplex stream */
-    if( stream->input && stream->output )
-    {
-        if( outputSpace >= framesTarget )
-            *framesAvail = outputSpace;
-        /* If input didn't make the target, keep the output count instead (input underflow) */
-        if( (inputData >= framesTarget) && (inputData < outputSpace) )
-            *framesAvail = inputData;
-    }
-    else
-    {
-        *framesAvail = stream->input ? inputData : outputSpace;
-    }
-
-error:
-    return result;
-}
-
-
-/** Obtain recording, current and playback timestamps of stream.
- The current time is determined by the system clock. This "now" timestamp occurs at the
- forefront of recording (and playback in the full-duplex case), which happens later than the
- input timestamp by an amount equal to the total number of recorded frames in the input buffer.
- The output timestamp indicates when the next generated sample will actually be played. This
- happens after all the samples currently in the output buffer are played. The output timestamp
- therefore follows the current timestamp by an amount equal to the number of frames yet to be
- played back in the output buffer.
-
- If the current timestamp is the present, the input timestamp is in the past and the output
- timestamp is in the future.
-
- @param stream Pointer to stream struct
-
- @param timeInfo Pointer to timeInfo struct that will contain timestamps
- */
-static void PaAsiHpi_CalculateTimeInfo( PaAsiHpiStream *stream, PaStreamCallbackTimeInfo *timeInfo )
-{
-    PaAsiHpiStreamInfo streamInfo;
-    double sampleRate;
-
-    assert( stream );
-    assert( timeInfo );
-    sampleRate = stream->baseStreamRep.streamInfo.sampleRate;
-
-    /* The current time ("now") is at the forefront of both recording and playback */
-    timeInfo->currentTime = GetStreamTime( (PaStream *)stream );
-    /* The last sample in the input buffer was recorded just now, so the first sample
-     happened (number of recorded samples)/sampleRate ago */
-    timeInfo->inputBufferAdcTime = timeInfo->currentTime;
-    if( stream->input )
-    {
-        PaAsiHpi_GetStreamInfo( stream->input, &streamInfo );
-        timeInfo->inputBufferAdcTime -= streamInfo.totalBufferedData / sampleRate;
-    }
-    /* The first of the outgoing samples will be played after all the samples in the output
-     buffer is done */
-    timeInfo->outputBufferDacTime = timeInfo->currentTime;
-    if( stream->output )
-    {
-        PaAsiHpi_GetStreamInfo( stream->output, &streamInfo );
-        timeInfo->outputBufferDacTime += streamInfo.totalBufferedData / sampleRate;
-    }
-}
-
-
-/** Read from HPI input stream and register buffers.
- This reads data from the HPI input stream (if it exists) and registers the temp stream
- buffers of both input and output streams with the buffer processor. In the process it also
- handles input underflows in the full-duplex case.
-
- @param stream Pointer to stream struct
-
- @param numFrames On entrance the number of available frames, on exit the number of
-                  received frames
-
- @param cbFlags Indicates overflows and underflows
-
- @return PortAudio error code
- */
-static PaError PaAsiHpi_BeginProcessing( PaAsiHpiStream *stream, unsigned long *numFrames,
-        PaStreamCallbackFlags *cbFlags )
-{
-    PaError result = paNoError;
-
-    assert( stream );
-    if( *numFrames > stream->maxFramesPerHostBuffer )
-        *numFrames = stream->maxFramesPerHostBuffer;
-
-    if( stream->input )
-    {
-        PaAsiHpiStreamInfo info;
-        HPI_DATA data;
-        HW32 framesToGet = *numFrames;
-
-        /* Check for overflows and underflows yet again */
-        PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->input, &info ) );
-        if( info.overflow )
-        {
-            *cbFlags |= paInputOverflow;
-        }
-        /* Input underflow if less than expected number of samples pitch up */
-        if( framesToGet > info.availableFrames )
-        {
-            PaUtilZeroer *zeroer;
-            PaSampleFormat inputFormat;
-
-            /* Never call an input-only stream with InputUnderflow set */
-            if( stream->output )
-                *cbFlags |= paInputUnderflow;
-            framesToGet = info.availableFrames;
-            /* Fill temp buffer with silence (to make up for missing input samples) */
-            inputFormat = PaAsiHpi_HpiToPaFormat( stream->input->hpiFormat.wFormat );
-            zeroer = PaUtil_SelectZeroer( inputFormat );
-            zeroer(stream->input->tempBuffer, 1,
-                   stream->input->tempBufferSize / Pa_GetSampleSize(inputFormat) );
-        }
-
-        /* Setup HPI data structure around temp buffer */
-        HPI_DataCreate( &data, &stream->input->hpiFormat, stream->input->tempBuffer,
-                        framesToGet * stream->input->bytesPerFrame );
-        /* Read block of data into temp buffer */
-        PA_ASIHPI_UNLESS_( HPI_InStreamRead( stream->input->hpiDevice->subSys,
-                                             stream->input->hpiStream, &data ),
-                           paUnanticipatedHostError );
-        /* Register temp buffer with buffer processor (always FULL buffer) */
-        PaUtil_SetInputFrameCount( &stream->bufferProcessor, *numFrames );
-        /* HPI interface only allows interleaved channels */
-        PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
-                                            0, stream->input->tempBuffer,
-                                            stream->input->hpiFormat.wChannels );
-    }
-    if( stream->output )
-    {
-        /* Register temp buffer with buffer processor */
-        PaUtil_SetOutputFrameCount( &stream->bufferProcessor, *numFrames );
-        /* HPI interface only allows interleaved channels */
-        PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
-                                             0, stream->output->tempBuffer,
-                                             stream->output->hpiFormat.wChannels );
-    }
-
-error:
-    return result;
-}
-
-
-/** Flush output buffers to HPI output stream.
- This completes the processing cycle by writing the temp buffer to the HPI interface.
- Additional output underflows are caught before data is written to the stream, as this
- action typically remedies the underflow and hides it in the process.
-
- @param stream Pointer to stream struct
-
- @param numFrames The number of frames to write to the output stream
-
- @param cbFlags Indicates overflows and underflows
- */
-static PaError PaAsiHpi_EndProcessing( PaAsiHpiStream *stream, unsigned long numFrames,
-                                       PaStreamCallbackFlags *cbFlags )
-{
-    PaError result = paNoError;
-
-    assert( stream );
-
-    if( stream->output )
-    {
-        PaAsiHpiStreamInfo info;
-        HPI_DATA data;
-
-        /* Check for underflows after the (potentially time-consuming) callback */
-        PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->output, &info ) );
-        if( info.underflow )
-        {
-            *cbFlags |= paOutputUnderflow;
-        }
-
-        /* Setup HPI data structure around temp buffer */
-        HPI_DataCreate( &data, &stream->output->hpiFormat, stream->output->tempBuffer,
-                        numFrames * stream->output->bytesPerFrame );
-        /* Write temp buffer to HPI stream */
-        PA_ASIHPI_UNLESS_( HPI_OutStreamWrite( stream->output->hpiDevice->subSys,
-                                               stream->output->hpiStream, &data ),
-                           paUnanticipatedHostError );
-    }
-
-error:
-    return result;
-}
-
-
-/** Main callback engine.
- This function runs in a separate thread and does all the work of fetching audio data from
- the AudioScience card via the HPI interface, feeding it to the user callback via the buffer
- processor, and delivering the resulting output data back to the card via HPI calls.
- It is started and terminated when the PortAudio stream is started and stopped, and starts
- the HPI streams on startup.
-
- @param userData A pointer to an open stream previously created with Pa_OpenStream.
-*/
-static void *CallbackThreadFunc( void *userData )
-{
-    PaError result = paNoError;
-    PaAsiHpiStream *stream = (PaAsiHpiStream *) userData;
-    int callbackResult = paContinue;
-
-    assert( stream );
-
-    /* Cleanup routine stops streams on thread exit */
-    pthread_cleanup_push( &PaAsiHpi_OnThreadExit, stream );
-
-    /* Start HPI streams and notify parent when we're done */
-    PA_ENSURE_( PaUnixThread_PrepareNotify( &stream->thread ) );
-    /* Buffer will be primed with silence */
-    PA_ENSURE_( PaAsiHpi_StartStream( stream, 0 ) );
-    PA_ENSURE_( PaUnixThread_NotifyParent( &stream->thread ) );
-
-    /* MAIN LOOP */
-    while( 1 )
-    {
-        PaStreamCallbackFlags cbFlags = 0;
-        unsigned long framesAvail, framesGot;
-
-        pthread_testcancel();
-
-        /** @concern StreamStop if the main thread has requested a stop and the stream has not
-        * been effectively stopped we signal this condition by modifying callbackResult
-        * (we'll want to flush buffered output). */
-        if( PaUnixThread_StopRequested( &stream->thread ) && (callbackResult == paContinue) )
-        {
-            PA_DEBUG(( "Setting callbackResult to paComplete\n" ));
-            callbackResult = paComplete;
-        }
-
-        /* Start winding down thread if requested */
-        if( callbackResult != paContinue )
-        {
-            stream->callbackAbort = (callbackResult == paAbort);
-            if( stream->callbackAbort ||
-                    /** @concern BlockAdaption: Go on if adaption buffers are empty */
-                    PaUtil_IsBufferProcessorOutputEmpty( &stream->bufferProcessor ) )
-            {
-                goto end;
-            }
-            PA_DEBUG(( "%s: Flushing buffer processor\n", __FUNCTION__ ));
-            /* There is still buffered output that needs to be processed */
-        }
-
-        /* SLEEP */
-        /* Wait for data (or buffer space) to become available. This basically sleeps and
-        polls the HPI interface until a full block of frames can be moved. */
-        PA_ENSURE_( PaAsiHpi_WaitForFrames( stream, &framesAvail, &cbFlags ) );
-
-        /* Consume buffer space. Once we have a number of frames available for consumption we
-        must retrieve the data from the HPI interface and pass it to the PA buffer processor.
-        We should be prepared to process several chunks successively. */
-        while( framesAvail > 0 )
-        {
-            PaStreamCallbackTimeInfo timeInfo = {0, 0, 0};
-
-            pthread_testcancel();
-
-            framesGot = framesAvail;
-            if( stream->bufferProcessor.hostBufferSizeMode == paUtilFixedHostBufferSize )
-            {
-                /* We've committed to a fixed host buffer size, stick to that */
-                framesGot = framesGot >= stream->maxFramesPerHostBuffer ? stream->maxFramesPerHostBuffer : 0;
-            }
-            else
-            {
-                /* We've committed to an upper bound on the size of host buffers */
-                assert( stream->bufferProcessor.hostBufferSizeMode == paUtilBoundedHostBufferSize );
-                framesGot = PA_MIN( framesGot, stream->maxFramesPerHostBuffer );
-            }
-
-            /* Obtain buffer timestamps */
-            PaAsiHpi_CalculateTimeInfo( stream, &timeInfo );
-            PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, cbFlags );
-            /* CPU load measurement should include processing activivity external to the stream callback */
-            PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
-            if( framesGot > 0 )
-            {
-                /* READ FROM HPI INPUT STREAM */
-                PA_ENSURE_( PaAsiHpi_BeginProcessing( stream, &framesGot, &cbFlags ) );
-                /* Input overflow in a full-duplex stream makes for interesting times */
-                if( stream->input && stream->output && (cbFlags & paInputOverflow) )
-                {
-                    /* Special full-duplex paNeverDropInput mode */
-                    if( stream->neverDropInput )
-                    {
-                        PaUtil_SetNoOutput( &stream->bufferProcessor );
-                        cbFlags |= paOutputOverflow;
-                    }
-                }
-                /* CALL USER CALLBACK WITH INPUT DATA, AND OBTAIN OUTPUT DATA */
-                PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );
-                /* Clear overflow and underflow information (but PaAsiHpi_EndProcessing might
-                still show up output underflow that will carry over to next round) */
-                cbFlags = 0;
-                /*  WRITE TO HPI OUTPUT STREAM */
-                PA_ENSURE_( PaAsiHpi_EndProcessing( stream, framesGot, &cbFlags ) );
-                /* Advance frame counter */
-                framesAvail -= framesGot;
-            }
-            PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesGot );
-
-            if( framesGot == 0 )
-            {
-                /* Go back to polling for more frames */
-                break;
-
-            }
-            if( callbackResult != paContinue )
-                break;
-        }
-    }
-
-    /* This code is unreachable, but important to include regardless because it
-     * is possibly a macro with a closing brace to match the opening brace in
-     * pthread_cleanup_push() above.  The documentation states that they must
-     * always occur in pairs. */
-    pthread_cleanup_pop( 1 );
-
-end:
-    /* Indicates normal exit of callback, as opposed to the thread getting killed explicitly */
-    stream->callbackFinished = 1;
-    PA_DEBUG(( "%s: Thread %d exiting (callbackResult = %d)\n ",
-               __FUNCTION__, pthread_self(), callbackResult ));
-    /* Exit from thread and report any PortAudio error in the process */
-    PaUnixThreading_EXIT( result );
-error:
-    goto end;
-}
-
-/* --------------------------- Blocking Interface --------------------------- */
-
-/* As separate stream interfaces are used for blocking and callback streams, the following
- functions can be guaranteed to only be called for blocking streams. */
-
-/** Read data from input stream.
- This reads the indicated number of frames into the supplied buffer from an input stream,
- and blocks until this is done.
-
- @param s Pointer to PortAudio stream
-
- @param buffer Pointer to buffer that will receive interleaved data (or an array of pointers
-               to a buffer for each non-interleaved channel)
-
- @param frames Number of frames to read from stream
-
- @return PortAudio error code (also indicates overflow via paInputOverflowed)
- */
-static PaError ReadStream( PaStream *s,
-                           void *buffer,
-                           unsigned long frames )
-{
-    PaError result = paNoError;
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-    PaAsiHpiStreamInfo info;
-    void *userBuffer;
-
-    assert( stream );
-    PA_UNLESS_( stream->input, paCanNotReadFromAnOutputOnlyStream );
-
-    /* Check for input overflow since previous call to ReadStream */
-    PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->input, &info ) );
-    if( info.overflow )
-    {
-        result = paInputOverflowed;
-    }
-
-    /* NB Make copy of user buffer pointers, since they are advanced by buffer processor */
-    if( stream->bufferProcessor.userInputIsInterleaved )
-    {
-        userBuffer = buffer;
-    }
-    else
-    {
-        /* Copy channels into local array */
-        userBuffer = stream->blockingUserBufferCopy;
-        memcpy( userBuffer, buffer, sizeof (void *) * stream->input->hpiFormat.wChannels );
-    }
-
-    while( frames > 0 )
-    {
-        unsigned long framesGot, framesAvail;
-        PaStreamCallbackFlags cbFlags = 0;
-
-        PA_ENSURE_( PaAsiHpi_WaitForFrames( stream, &framesAvail, &cbFlags ) );
-        framesGot = PA_MIN( framesAvail, frames );
-        PA_ENSURE_( PaAsiHpi_BeginProcessing( stream, &framesGot, &cbFlags ) );
-
-        if( framesGot > 0 )
-        {
-            framesGot = PaUtil_CopyInput( &stream->bufferProcessor, &userBuffer, framesGot );
-            PA_ENSURE_( PaAsiHpi_EndProcessing( stream, framesGot, &cbFlags ) );
-            /* Advance frame counter */
-            frames -= framesGot;
-        }
-    }
-
-error:
-    return result;
-}
-
-
-/** Write data to output stream.
- This writes the indicated number of frames from the supplied buffer to an output stream,
- and blocks until this is done.
-
- @param s Pointer to PortAudio stream
-
- @param buffer Pointer to buffer that provides interleaved data (or an array of pointers
-               to a buffer for each non-interleaved channel)
-
- @param frames Number of frames to write to stream
-
- @return PortAudio error code (also indicates underflow via paOutputUnderflowed)
- */
-static PaError WriteStream( PaStream *s,
-                            const void *buffer,
-                            unsigned long frames )
-{
-    PaError result = paNoError;
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-    PaAsiHpiStreamInfo info;
-    const void *userBuffer;
-
-    assert( stream );
-    PA_UNLESS_( stream->output, paCanNotWriteToAnInputOnlyStream );
-
-    /* Check for output underflow since previous call to WriteStream */
-    PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->output, &info ) );
-    if( info.underflow )
-    {
-        result = paOutputUnderflowed;
-    }
-
-    /* NB Make copy of user buffer pointers, since they are advanced by buffer processor */
-    if( stream->bufferProcessor.userOutputIsInterleaved )
-    {
-        userBuffer = buffer;
-    }
-    else
-    {
-        /* Copy channels into local array */
-        userBuffer = stream->blockingUserBufferCopy;
-        memcpy( (void *)userBuffer, buffer, sizeof (void *) * stream->output->hpiFormat.wChannels );
-    }
-
-    while( frames > 0 )
-    {
-        unsigned long framesGot, framesAvail;
-        PaStreamCallbackFlags cbFlags = 0;
-
-        PA_ENSURE_( PaAsiHpi_WaitForFrames( stream, &framesAvail, &cbFlags ) );
-        framesGot = PA_MIN( framesAvail, frames );
-        PA_ENSURE_( PaAsiHpi_BeginProcessing( stream, &framesGot, &cbFlags ) );
-
-        if( framesGot > 0 )
-        {
-            framesGot = PaUtil_CopyOutput( &stream->bufferProcessor, &userBuffer, framesGot );
-            PA_ENSURE_( PaAsiHpi_EndProcessing( stream, framesGot, &cbFlags ) );
-            /* Advance frame counter */
-            frames -= framesGot;
-        }
-    }
-
-error:
-    return result;
-}
-
-
-/** Number of frames that can be read from input stream without blocking.
-
- @param s Pointer to PortAudio stream
-
- @return Number of frames, or PortAudio error code
- */
-static signed long GetStreamReadAvailable( PaStream *s )
-{
-    PaError result = paNoError;
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-    PaAsiHpiStreamInfo info;
-
-    assert( stream );
-    PA_UNLESS_( stream->input, paCanNotReadFromAnOutputOnlyStream );
-
-    PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->input, &info ) );
-    /* Round down to the nearest host buffer multiple */
-    result = (info.availableFrames / stream->maxFramesPerHostBuffer) * stream->maxFramesPerHostBuffer;
-    if( info.overflow )
-    {
-        result = paInputOverflowed;
-    }
-
-error:
-    return result;
-}
-
-
-/** Number of frames that can be written to output stream without blocking.
-
- @param s Pointer to PortAudio stream
-
- @return Number of frames, or PortAudio error code
- */
-static signed long GetStreamWriteAvailable( PaStream *s )
-{
-    PaError result = paNoError;
-    PaAsiHpiStream *stream = (PaAsiHpiStream*)s;
-    PaAsiHpiStreamInfo info;
-
-    assert( stream );
-    PA_UNLESS_( stream->output, paCanNotWriteToAnInputOnlyStream );
-
-    PA_ENSURE_( PaAsiHpi_GetStreamInfo( stream->output, &info ) );
-    /* Round down to the nearest host buffer multiple */
-    result = (info.availableFrames / stream->maxFramesPerHostBuffer) * stream->maxFramesPerHostBuffer;
-    if( info.underflow )
-    {
-        result = paOutputUnderflowed;
-    }
-
-error:
-    return result;
-}
diff --git a/portaudio/unused/hostapi/dsound/pa_win_ds.c b/portaudio/unused/hostapi/dsound/pa_win_ds.c
deleted file mode 100644
index b413be93cf66ab534a9b2d371cb05bd5c0a19e21..0000000000000000000000000000000000000000
--- a/portaudio/unused/hostapi/dsound/pa_win_ds.c
+++ /dev/null
@@ -1,2197 +0,0 @@
-/*
- * $Id: pa_win_ds.c 1229 2007-06-15 16:11:11Z rossb $
- * Portable Audio I/O Library DirectSound implementation
- *
- * Authors: Phil Burk, Robert Marsanyi & Ross Bencina
- * Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2006 Ross Bencina, Phil Burk, Robert Marsanyi
- *
- * 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
- @ingroup hostaip_src
-
-    @todo implement paInputOverflow callback status flag
-    
-    @todo implement paNeverDropInput.
-
-    @todo implement host api specific extension to set i/o buffer sizes in frames
-
-    @todo implement initialisation of PaDeviceInfo default*Latency fields (currently set to 0.)
-
-    @todo implement ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable
-
-    @todo audit handling of DirectSound result codes - in many cases we could convert a HRESULT into
-        a native portaudio error code. Standard DirectSound result codes are documented at msdn.
-
-    @todo implement IsFormatSupported
-
-    @todo check that CoInitialize() CoUninitialize() are always correctly
-        paired, even in error cases.
-
-    @todo call PaUtil_SetLastHostErrorInfo with a specific error string (currently just "DSound error").
-
-    @todo make sure all buffers have been played before stopping the stream
-        when the stream callback returns paComplete
-
-    old TODOs from phil, need to work out if these have been done:
-        O- fix "patest_stop.c"
-*/
-
-#include <stdio.h>
-#include <string.h> /* strlen() */
-
-#include "pa_util.h"
-#include "pa_allocation.h"
-#include "pa_hostapi.h"
-#include "pa_stream.h"
-#include "pa_cpuload.h"
-#include "pa_process.h"
-#include "pa_debugprint.h"
-
-#include "pa_win_ds_dynlink.h"
-
-#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */
-#pragma comment( lib, "dsound.lib" )
-#pragma comment( lib, "winmm.lib" )
-#endif
-
-/*
- provided in newer platform sdks and x64
- */
-#ifndef DWORD_PTR
-#define DWORD_PTR DWORD
-#endif
-
-#define PRINT(x) PA_DEBUG(x);
-#define ERR_RPT(x) PRINT(x)
-#define DBUG(x)   PRINT(x)
-#define DBUGX(x)  PRINT(x)
-
-#define PA_USE_HIGH_LATENCY   (0)
-#if PA_USE_HIGH_LATENCY
-#define PA_WIN_9X_LATENCY     (500)
-#define PA_WIN_NT_LATENCY     (600)
-#else
-#define PA_WIN_9X_LATENCY     (140)
-#define PA_WIN_NT_LATENCY     (280)
-#endif
-
-#define PA_WIN_WDM_LATENCY       (120)
-
-#define SECONDS_PER_MSEC      (0.001)
-#define MSEC_PER_SECOND       (1000)
-
-/* prototypes for functions declared in this file */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
-                           PaStream** s,
-                           const PaStreamParameters *inputParameters,
-                           const PaStreamParameters *outputParameters,
-                           double sampleRate,
-                           unsigned long framesPerBuffer,
-                           PaStreamFlags streamFlags,
-                           PaStreamCallback *streamCallback,
-                           void *userData );
-static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
-                                  const PaStreamParameters *inputParameters,
-                                  const PaStreamParameters *outputParameters,
-                                  double sampleRate );
-static PaError CloseStream( PaStream* stream );
-static PaError StartStream( PaStream *stream );
-static PaError StopStream( PaStream *stream );
-static PaError AbortStream( PaStream *stream );
-static PaError IsStreamStopped( PaStream *s );
-static PaError IsStreamActive( PaStream *stream );
-static PaTime GetStreamTime( PaStream *stream );
-static double GetStreamCpuLoad( PaStream* stream );
-static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
-static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
-static signed long GetStreamReadAvailable( PaStream* stream );
-static signed long GetStreamWriteAvailable( PaStream* stream );
-
-
-/* FIXME: should convert hr to a string */
-#define PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr ) \
-    PaUtil_SetLastHostErrorInfo( paDirectSound, hr, "DirectSound error" )
-
-/************************************************* DX Prototypes **********/
-static BOOL CALLBACK CollectGUIDsProc(LPGUID lpGUID,
-                                     LPCTSTR lpszDesc,
-                                     LPCTSTR lpszDrvName,
-                                     LPVOID lpContext );
-
-/************************************************************************************/
-/********************** Structures **************************************************/
-/************************************************************************************/
-/* PaWinDsHostApiRepresentation - host api datastructure specific to this implementation */
-
-typedef struct PaWinDsDeviceInfo
-{
-    GUID                             guid;
-    GUID                            *lpGUID;
-    double                           sampleRates[3];
-} PaWinDsDeviceInfo;
-
-typedef struct
-{
-    PaUtilHostApiRepresentation inheritedHostApiRep;
-    PaUtilStreamInterface    callbackStreamInterface;
-    PaUtilStreamInterface    blockingStreamInterface;
-
-    PaUtilAllocationGroup   *allocations;
-
-    /* implementation specific data goes here */
-    PaWinDsDeviceInfo       *winDsDeviceInfos;
-
-} PaWinDsHostApiRepresentation;
-
-
-/* PaWinDsStream - a stream data structure specifically for this implementation */
-
-typedef struct PaWinDsStream
-{
-    PaUtilStreamRepresentation streamRepresentation;
-    PaUtilCpuLoadMeasurer cpuLoadMeasurer;
-    PaUtilBufferProcessor bufferProcessor;
-
-/* DirectSound specific data. */
-
-/* Output */
-    LPDIRECTSOUND        pDirectSound;
-    LPDIRECTSOUNDBUFFER  pDirectSoundOutputBuffer;
-    DWORD                outputBufferWriteOffsetBytes;     /* last write position */
-    INT                  outputBufferSizeBytes;
-    INT                  bytesPerOutputFrame;
-    /* Try to detect play buffer underflows. */
-    LARGE_INTEGER        perfCounterTicksPerBuffer; /* counter ticks it should take to play a full buffer */
-    LARGE_INTEGER        previousPlayTime;
-    UINT                 previousPlayCursor;
-    UINT                 outputUnderflowCount;
-    BOOL                 outputIsRunning;
-    /* use double which lets us can play for several thousand years with enough precision */
-    double               dsw_framesWritten;
-    double               framesPlayed;
-/* Input */
-    LPDIRECTSOUNDCAPTURE pDirectSoundCapture;
-    LPDIRECTSOUNDCAPTUREBUFFER   pDirectSoundInputBuffer;
-    INT                  bytesPerInputFrame;
-    UINT                 readOffset;      /* last read position */
-    UINT                 inputSize;
-
-    
-    MMRESULT         timerID;
-    int              framesPerDSBuffer;
-    double           framesWritten;
-    double           secondsPerHostByte; /* Used to optimize latency calculation for outTime */
-
-    PaStreamCallbackFlags callbackFlags;
-    
-/* FIXME - move all below to PaUtilStreamRepresentation */
-    volatile int     isStarted;
-    volatile int     isActive;
-    volatile int     stopProcessing; /* stop thread once existing buffers have been returned */
-    volatile int     abortProcessing; /* stop thread immediately */
-} PaWinDsStream;
-
-
-/************************************************************************************
-** Duplicate the input string using the allocations allocator.
-** A NULL string is converted to a zero length string.
-** If memory cannot be allocated, NULL is returned.
-**/
-static char *DuplicateDeviceNameString( PaUtilAllocationGroup *allocations, const char* src )
-{
-    char *result = 0;
-    
-    if( src != NULL )
-    {
-        size_t len = strlen(src);
-        result = (char*)PaUtil_GroupAllocateMemory( allocations, (long)(len + 1) );
-        if( result )
-            memcpy( (void *) result, src, len+1 );
-    }
-    else
-    {
-        result = (char*)PaUtil_GroupAllocateMemory( allocations, 1 );
-        if( result )
-            result[0] = '\0';
-    }
-
-    return result;
-}
-
-/************************************************************************************
-** DSDeviceNameAndGUID, DSDeviceNameAndGUIDVector used for collecting preliminary
-** information during device enumeration.
-*/
-typedef struct DSDeviceNameAndGUID{
-    char *name; // allocated from parent's allocations, never deleted by this structure
-    GUID guid;
-    LPGUID lpGUID;
-} DSDeviceNameAndGUID;
-
-typedef struct DSDeviceNameAndGUIDVector{
-    PaUtilAllocationGroup *allocations;
-    PaError enumerationError;
-
-    int count;
-    int free;
-    DSDeviceNameAndGUID *items; // Allocated using LocalAlloc()
-} DSDeviceNameAndGUIDVector;
-
-static PaError InitializeDSDeviceNameAndGUIDVector(
-        DSDeviceNameAndGUIDVector *guidVector, PaUtilAllocationGroup *allocations )
-{
-    PaError result = paNoError;
-
-    guidVector->allocations = allocations;
-    guidVector->enumerationError = paNoError;
-
-    guidVector->count = 0;
-    guidVector->free = 8;
-    guidVector->items = (DSDeviceNameAndGUID*)LocalAlloc( LMEM_FIXED, sizeof(DSDeviceNameAndGUID) * guidVector->free );
-    if( guidVector->items == NULL )
-        result = paInsufficientMemory;
-    
-    return result;
-}
-
-static PaError ExpandDSDeviceNameAndGUIDVector( DSDeviceNameAndGUIDVector *guidVector )
-{
-    PaError result = paNoError;
-    DSDeviceNameAndGUID *newItems;
-    int i;
-    
-    /* double size of vector */
-    int size = guidVector->count + guidVector->free;
-    guidVector->free += size;
-
-    newItems = (DSDeviceNameAndGUID*)LocalAlloc( LMEM_FIXED, sizeof(DSDeviceNameAndGUID) * size * 2 );
-    if( newItems == NULL )
-    {
-        result = paInsufficientMemory;
-    }
-    else
-    {
-        for( i=0; i < guidVector->count; ++i )
-        {
-            newItems[i].name = guidVector->items[i].name;
-            if( guidVector->items[i].lpGUID == NULL )
-            {
-                newItems[i].lpGUID = NULL;
-            }
-            else
-            {
-                newItems[i].lpGUID = &newItems[i].guid;
-                memcpy( &newItems[i].guid, guidVector->items[i].lpGUID, sizeof(GUID) );;
-            }
-        }
-
-        LocalFree( guidVector->items );
-        guidVector->items = newItems;
-    }                                
-
-    return result;
-}
-
-/*
-    it's safe to call DSDeviceNameAndGUIDVector multiple times
-*/
-static PaError TerminateDSDeviceNameAndGUIDVector( DSDeviceNameAndGUIDVector *guidVector )
-{
-    PaError result = paNoError;
-
-    if( guidVector->items != NULL )
-    {
-        if( LocalFree( guidVector->items ) != NULL )
-            result = paInsufficientMemory;              /** @todo this isn't the correct error to return from a deallocation failure */
-
-        guidVector->items = NULL;
-    }
-
-    return result;
-}
-
-/************************************************************************************
-** Collect preliminary device information during DirectSound enumeration 
-*/
-static BOOL CALLBACK CollectGUIDsProc(LPGUID lpGUID,
-                                     LPCTSTR lpszDesc,
-                                     LPCTSTR lpszDrvName,
-                                     LPVOID lpContext )
-{
-    DSDeviceNameAndGUIDVector *namesAndGUIDs = (DSDeviceNameAndGUIDVector*)lpContext;
-    PaError error;
-
-    (void) lpszDrvName; /* unused variable */
-
-    if( namesAndGUIDs->free == 0 )
-    {
-        error = ExpandDSDeviceNameAndGUIDVector( namesAndGUIDs );
-        if( error != paNoError )
-        {
-            namesAndGUIDs->enumerationError = error;
-            return FALSE;
-        }
-    }
-    
-    /* Set GUID pointer, copy GUID to storage in DSDeviceNameAndGUIDVector. */
-    if( lpGUID == NULL )
-    {
-        namesAndGUIDs->items[namesAndGUIDs->count].lpGUID = NULL;
-    }
-    else
-    {
-        namesAndGUIDs->items[namesAndGUIDs->count].lpGUID =
-                &namesAndGUIDs->items[namesAndGUIDs->count].guid;
-      
-        memcpy( &namesAndGUIDs->items[namesAndGUIDs->count].guid, lpGUID, sizeof(GUID) );
-    }
-
-    namesAndGUIDs->items[namesAndGUIDs->count].name =
-            DuplicateDeviceNameString( namesAndGUIDs->allocations, lpszDesc );
-    if( namesAndGUIDs->items[namesAndGUIDs->count].name == NULL )
-    {
-        namesAndGUIDs->enumerationError = paInsufficientMemory;
-        return FALSE;
-    }
-
-    ++namesAndGUIDs->count;
-    --namesAndGUIDs->free;
-    
-    return TRUE;
-}
-
-
-/* 
-    GUIDs for emulated devices which we blacklist below.
-    are there more than two of them??
-*/
-
-GUID IID_IRolandVSCEmulated1 = {0xc2ad1800, 0xb243, 0x11ce, 0xa8, 0xa4, 0x00, 0xaa, 0x00, 0x6c, 0x45, 0x01};
-GUID IID_IRolandVSCEmulated2 = {0xc2ad1800, 0xb243, 0x11ce, 0xa8, 0xa4, 0x00, 0xaa, 0x00, 0x6c, 0x45, 0x02};
-
-
-#define PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_  (13) /* must match array length below */
-static double defaultSampleRateSearchOrder_[] =
-    { 44100.0, 48000.0, 32000.0, 24000.0, 22050.0, 88200.0, 96000.0, 192000.0,
-        16000.0, 12000.0, 11025.0, 9600.0, 8000.0 };
-
-
-/************************************************************************************
-** Extract capabilities from an output device, and add it to the device info list
-** if successful. This function assumes that there is enough room in the
-** device info list to accomodate all entries.
-**
-** The device will not be added to the device list if any errors are encountered.
-*/
-static PaError AddOutputDeviceInfoFromDirectSound(
-        PaWinDsHostApiRepresentation *winDsHostApi, char *name, LPGUID lpGUID )
-{
-    PaUtilHostApiRepresentation  *hostApi = &winDsHostApi->inheritedHostApiRep;
-    PaDeviceInfo                 *deviceInfo = hostApi->deviceInfos[hostApi->info.deviceCount];
-    PaWinDsDeviceInfo            *winDsDeviceInfo = &winDsHostApi->winDsDeviceInfos[hostApi->info.deviceCount];
-    HRESULT                       hr;
-    LPDIRECTSOUND                 lpDirectSound;
-    DSCAPS                        caps;
-    int                           deviceOK = TRUE;
-    PaError                       result = paNoError;
-    int                           i;
-    
-    /* Copy GUID to the device info structure. Set pointer. */
-    if( lpGUID == NULL )
-    {
-        winDsDeviceInfo->lpGUID = NULL;
-    }
-    else
-    {
-        memcpy( &winDsDeviceInfo->guid, lpGUID, sizeof(GUID) );
-        winDsDeviceInfo->lpGUID = &winDsDeviceInfo->guid;
-    }
-
-    
-    if( lpGUID )
-    {
-        if (IsEqualGUID (&IID_IRolandVSCEmulated1,lpGUID) ||
-            IsEqualGUID (&IID_IRolandVSCEmulated2,lpGUID) )
-        {
-            PA_DEBUG(("BLACKLISTED: %s \n",name));
-            return paNoError;
-        }
-    }
-
-    /* Create a DirectSound object for the specified GUID
-        Note that using CoCreateInstance doesn't work on windows CE.
-    */
-    hr = paWinDsDSoundEntryPoints.DirectSoundCreate( lpGUID, &lpDirectSound, NULL );
-
-    /** try using CoCreateInstance because DirectSoundCreate was hanging under
-        some circumstances - note this was probably related to the
-        #define BOOL short bug which has now been fixed
-        @todo delete this comment and the following code once we've ensured
-        there is no bug.
-    */
-    /*
-    hr = CoCreateInstance( &CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
-            &IID_IDirectSound, (void**)&lpDirectSound );
-
-    if( hr == S_OK )
-    {
-        hr = IDirectSound_Initialize( lpDirectSound, lpGUID );
-    }
-    */
-    
-    if( hr != DS_OK )
-    {
-        if (hr == DSERR_ALLOCATED)
-            PA_DEBUG(("AddOutputDeviceInfoFromDirectSound %s DSERR_ALLOCATED\n",name));
-        DBUG(("Cannot create DirectSound for %s. Result = 0x%x\n", name, hr ));
-        if (lpGUID)
-            DBUG(("%s's GUID: {0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x, 0x%x} \n",
-                 name,
-                 lpGUID->Data1,
-                 lpGUID->Data2,
-                 lpGUID->Data3,
-                 lpGUID->Data4[0],
-                 lpGUID->Data4[1],
-                 lpGUID->Data4[2],
-                 lpGUID->Data4[3],
-                 lpGUID->Data4[4],
-                 lpGUID->Data4[5],
-                 lpGUID->Data4[6],
-                 lpGUID->Data4[7]));
-
-        deviceOK = FALSE;
-    }
-    else
-    {
-        /* Query device characteristics. */
-        memset( &caps, 0, sizeof(caps) ); 
-        caps.dwSize = sizeof(caps);
-        hr = IDirectSound_GetCaps( lpDirectSound, &caps );
-        if( hr != DS_OK )
-        {
-            DBUG(("Cannot GetCaps() for DirectSound device %s. Result = 0x%x\n", name, hr ));
-            deviceOK = FALSE;
-        }
-        else
-        {
-
-#ifndef PA_NO_WMME
-            if( caps.dwFlags & DSCAPS_EMULDRIVER )
-            {
-                /* If WMME supported, then reject Emulated drivers because they are lousy. */
-                deviceOK = FALSE;
-            }
-#endif
-
-            if( deviceOK )
-            {
-                deviceInfo->maxInputChannels = 0;
-                /* Mono or stereo device? */
-                deviceInfo->maxOutputChannels = ( caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;
-
-                deviceInfo->defaultLowInputLatency = 0.;    /** @todo IMPLEMENT ME */
-                deviceInfo->defaultLowOutputLatency = 0.;   /** @todo IMPLEMENT ME */
-                deviceInfo->defaultHighInputLatency = 0.;   /** @todo IMPLEMENT ME */
-                deviceInfo->defaultHighOutputLatency = 0.;  /** @todo IMPLEMENT ME */
-                
-                /* initialize defaultSampleRate */
-                
-                if( caps.dwFlags & DSCAPS_CONTINUOUSRATE )
-                {
-                    /* initialize to caps.dwMaxSecondarySampleRate incase none of the standard rates match */
-                    deviceInfo->defaultSampleRate = caps.dwMaxSecondarySampleRate;
-
-                    for( i = 0; i < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++i )
-                    {
-                        if( defaultSampleRateSearchOrder_[i] >= caps.dwMinSecondarySampleRate
-                                && defaultSampleRateSearchOrder_[i] <= caps.dwMaxSecondarySampleRate ){
-
-                            deviceInfo->defaultSampleRate = defaultSampleRateSearchOrder_[i];
-                            break;
-                        }
-                    }
-                }
-                else if( caps.dwMinSecondarySampleRate == caps.dwMaxSecondarySampleRate )
-                {
-                    if( caps.dwMinSecondarySampleRate == 0 )
-                    {
-                        /*
-                        ** On my Thinkpad 380Z, DirectSoundV6 returns min-max=0 !!
-                        ** But it supports continuous sampling.
-                        ** So fake range of rates, and hope it really supports it.
-                        */
-                        deviceInfo->defaultSampleRate = 44100.0f;
-
-                        DBUG(("PA - Reported rates both zero. Setting to fake values for device #%s\n", name ));
-                    }
-                    else
-                    {
-	                    deviceInfo->defaultSampleRate = caps.dwMaxSecondarySampleRate;
-                    }
-                }
-                else if( (caps.dwMinSecondarySampleRate < 1000.0) && (caps.dwMaxSecondarySampleRate > 50000.0) )
-                {
-                    /* The EWS88MT drivers lie, lie, lie. The say they only support two rates, 100 & 100000.
-                    ** But we know that they really support a range of rates!
-                    ** So when we see a ridiculous set of rates, assume it is a range.
-                    */
-                  deviceInfo->defaultSampleRate = 44100.0f;
-                  DBUG(("PA - Sample rate range used instead of two odd values for device #%s\n", name ));
-                }
-                else deviceInfo->defaultSampleRate = caps.dwMaxSecondarySampleRate;
-
-
-                //printf( "min %d max %d\n", caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate );
-                // dwFlags | DSCAPS_CONTINUOUSRATE 
-            }
-        }
-
-        IDirectSound_Release( lpDirectSound );
-    }
-
-    if( deviceOK )
-    {
-        deviceInfo->name = name;
-
-        if( lpGUID == NULL )
-            hostApi->info.defaultOutputDevice = hostApi->info.deviceCount;
-            
-        hostApi->info.deviceCount++;
-    }
-
-    return result;
-}
-
-
-/************************************************************************************
-** Extract capabilities from an input device, and add it to the device info list
-** if successful. This function assumes that there is enough room in the
-** device info list to accomodate all entries.
-**
-** The device will not be added to the device list if any errors are encountered.
-*/
-static PaError AddInputDeviceInfoFromDirectSoundCapture(
-        PaWinDsHostApiRepresentation *winDsHostApi, char *name, LPGUID lpGUID )
-{
-    PaUtilHostApiRepresentation  *hostApi = &winDsHostApi->inheritedHostApiRep;
-    PaDeviceInfo                 *deviceInfo = hostApi->deviceInfos[hostApi->info.deviceCount];
-    PaWinDsDeviceInfo            *winDsDeviceInfo = &winDsHostApi->winDsDeviceInfos[hostApi->info.deviceCount];
-    HRESULT                       hr;
-    LPDIRECTSOUNDCAPTURE          lpDirectSoundCapture;
-    DSCCAPS                       caps;
-    int                           deviceOK = TRUE;
-    PaError                       result = paNoError;
-    
-    /* Copy GUID to the device info structure. Set pointer. */
-    if( lpGUID == NULL )
-    {
-        winDsDeviceInfo->lpGUID = NULL;
-    }
-    else
-    {
-        winDsDeviceInfo->lpGUID = &winDsDeviceInfo->guid;
-        memcpy( &winDsDeviceInfo->guid, lpGUID, sizeof(GUID) );
-    }
-
-
-    hr = paWinDsDSoundEntryPoints.DirectSoundCaptureCreate( lpGUID, &lpDirectSoundCapture, NULL );
-
-    /** try using CoCreateInstance because DirectSoundCreate was hanging under
-        some circumstances - note this was probably related to the
-        #define BOOL short bug which has now been fixed
-        @todo delete this comment and the following code once we've ensured
-        there is no bug.
-    */
-    /*
-    hr = CoCreateInstance( &CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
-            &IID_IDirectSoundCapture, (void**)&lpDirectSoundCapture );
-    */
-    if( hr != DS_OK )
-    {
-        DBUG(("Cannot create Capture for %s. Result = 0x%x\n", name, hr ));
-        deviceOK = FALSE;
-    }
-    else
-    {
-        /* Query device characteristics. */
-        memset( &caps, 0, sizeof(caps) );
-        caps.dwSize = sizeof(caps);
-        hr = IDirectSoundCapture_GetCaps( lpDirectSoundCapture, &caps );
-        if( hr != DS_OK )
-        {
-            DBUG(("Cannot GetCaps() for Capture device %s. Result = 0x%x\n", name, hr ));
-            deviceOK = FALSE;
-        }
-        else
-        {
-#ifndef PA_NO_WMME
-            if( caps.dwFlags & DSCAPS_EMULDRIVER )
-            {
-                /* If WMME supported, then reject Emulated drivers because they are lousy. */
-                deviceOK = FALSE;
-            }
-#endif
-
-            if( deviceOK )
-            {
-                deviceInfo->maxInputChannels = caps.dwChannels;
-                deviceInfo->maxOutputChannels = 0;
-
-                deviceInfo->defaultLowInputLatency = 0.;    /** @todo IMPLEMENT ME */
-                deviceInfo->defaultLowOutputLatency = 0.;   /** @todo IMPLEMENT ME */
-                deviceInfo->defaultHighInputLatency = 0.;   /** @todo IMPLEMENT ME */
-                deviceInfo->defaultHighOutputLatency = 0.;  /** @todo IMPLEMENT ME */
-
-/*  constants from a WINE patch by Francois Gouget, see:
-    http://www.winehq.com/hypermail/wine-patches/2003/01/0290.html
-
-    ---
-    Date: Fri, 14 May 2004 10:38:12 +0200 (CEST)
-    From: Francois Gouget <fgouget@ ... .fr>
-    To: Ross Bencina <rbencina@ ... .au>
-    Subject: Re: Permission to use wine 48/96 wave patch in BSD licensed library
-
-    [snip]
-
-    I give you permission to use the patch below under the BSD license.
-    http://www.winehq.com/hypermail/wine-patches/2003/01/0290.html
-
-    [snip]
-*/
-#ifndef WAVE_FORMAT_48M08
-#define WAVE_FORMAT_48M08      0x00001000    /* 48     kHz, Mono,   8-bit  */
-#define WAVE_FORMAT_48S08      0x00002000    /* 48     kHz, Stereo, 8-bit  */
-#define WAVE_FORMAT_48M16      0x00004000    /* 48     kHz, Mono,   16-bit */
-#define WAVE_FORMAT_48S16      0x00008000    /* 48     kHz, Stereo, 16-bit */
-#define WAVE_FORMAT_96M08      0x00010000    /* 96     kHz, Mono,   8-bit  */
-#define WAVE_FORMAT_96S08      0x00020000    /* 96     kHz, Stereo, 8-bit  */
-#define WAVE_FORMAT_96M16      0x00040000    /* 96     kHz, Mono,   16-bit */
-#define WAVE_FORMAT_96S16      0x00080000    /* 96     kHz, Stereo, 16-bit */
-#endif
-
-                /* defaultSampleRate */
-                if( caps.dwChannels == 2 )
-                {
-                    if( caps.dwFormats & WAVE_FORMAT_4S16 )
-                        deviceInfo->defaultSampleRate = 44100.0;
-                    else if( caps.dwFormats & WAVE_FORMAT_48S16 )
-                        deviceInfo->defaultSampleRate = 48000.0;
-                    else if( caps.dwFormats & WAVE_FORMAT_2S16 )
-                        deviceInfo->defaultSampleRate = 22050.0;
-                    else if( caps.dwFormats & WAVE_FORMAT_1S16 )
-                        deviceInfo->defaultSampleRate = 11025.0;
-                    else if( caps.dwFormats & WAVE_FORMAT_96S16 )
-                        deviceInfo->defaultSampleRate = 96000.0;
-                    else
-                        deviceInfo->defaultSampleRate = 0.;
-                }
-                else if( caps.dwChannels == 1 )
-                {
-                    if( caps.dwFormats & WAVE_FORMAT_4M16 )
-                        deviceInfo->defaultSampleRate = 44100.0;
-                    else if( caps.dwFormats & WAVE_FORMAT_48M16 )
-                        deviceInfo->defaultSampleRate = 48000.0;
-                    else if( caps.dwFormats & WAVE_FORMAT_2M16 )
-                        deviceInfo->defaultSampleRate = 22050.0;
-                    else if( caps.dwFormats & WAVE_FORMAT_1M16 )
-                        deviceInfo->defaultSampleRate = 11025.0;
-                    else if( caps.dwFormats & WAVE_FORMAT_96M16 )
-                        deviceInfo->defaultSampleRate = 96000.0;
-                    else
-                        deviceInfo->defaultSampleRate = 0.;
-                }
-                else deviceInfo->defaultSampleRate = 0.;
-            }
-        }
-        
-        IDirectSoundCapture_Release( lpDirectSoundCapture );
-    }
-
-    if( deviceOK )
-    {
-        deviceInfo->name = name;
-
-        if( lpGUID == NULL )
-            hostApi->info.defaultInputDevice = hostApi->info.deviceCount;
-
-        hostApi->info.deviceCount++;
-    }
-
-    return result;
-}
-
-
-/***********************************************************************************/
-PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
-{
-    PaError result = paNoError;
-    int i, deviceCount;
-    PaWinDsHostApiRepresentation *winDsHostApi;
-    DSDeviceNameAndGUIDVector inputNamesAndGUIDs, outputNamesAndGUIDs;
-    PaDeviceInfo *deviceInfoArray;
-
-    HRESULT hr = CoInitialize(NULL);        /** @todo: should uninitialize too */
-    if( FAILED(hr) ){
-        return paUnanticipatedHostError;
-    }            
-
-    /* initialise guid vectors so they can be safely deleted on error */
-    inputNamesAndGUIDs.items = NULL;
-    outputNamesAndGUIDs.items = NULL;
-
-    PaWinDs_InitializeDSoundEntryPoints();
-
-    winDsHostApi = (PaWinDsHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinDsHostApiRepresentation) );
-    if( !winDsHostApi )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    winDsHostApi->allocations = PaUtil_CreateAllocationGroup();
-    if( !winDsHostApi->allocations )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    *hostApi = &winDsHostApi->inheritedHostApiRep;
-    (*hostApi)->info.structVersion = 1;
-    (*hostApi)->info.type = paDirectSound;
-    (*hostApi)->info.name = "Windows DirectSound";
-    
-    (*hostApi)->info.deviceCount = 0;
-    (*hostApi)->info.defaultInputDevice = paNoDevice;
-    (*hostApi)->info.defaultOutputDevice = paNoDevice;
-
-    
-/* DSound - enumerate devices to count them and to gather their GUIDs */
-
-
-    result = InitializeDSDeviceNameAndGUIDVector( &inputNamesAndGUIDs, winDsHostApi->allocations );
-    if( result != paNoError )
-        goto error;
-
-    result = InitializeDSDeviceNameAndGUIDVector( &outputNamesAndGUIDs, winDsHostApi->allocations );
-    if( result != paNoError )
-        goto error;
-
-    paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&inputNamesAndGUIDs );
-
-    paWinDsDSoundEntryPoints.DirectSoundEnumerate( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&outputNamesAndGUIDs );
-
-    if( inputNamesAndGUIDs.enumerationError != paNoError )
-    {
-        result = inputNamesAndGUIDs.enumerationError;
-        goto error;
-    }
-
-    if( outputNamesAndGUIDs.enumerationError != paNoError )
-    {
-        result = outputNamesAndGUIDs.enumerationError;
-        goto error;
-    }
-
-    deviceCount = inputNamesAndGUIDs.count + outputNamesAndGUIDs.count;
-
-    if( deviceCount > 0 )
-    {
-        /* allocate array for pointers to PaDeviceInfo structs */
-        (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
-                winDsHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount );
-        if( !(*hostApi)->deviceInfos )
-        {
-            result = paInsufficientMemory;
-            goto error;
-        }
-
-        /* allocate all PaDeviceInfo structs in a contiguous block */
-        deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
-                winDsHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount );
-        if( !deviceInfoArray )
-        {
-            result = paInsufficientMemory;
-            goto error;
-        }
-
-        /* allocate all DSound specific info structs in a contiguous block */
-        winDsHostApi->winDsDeviceInfos = (PaWinDsDeviceInfo*)PaUtil_GroupAllocateMemory(
-                winDsHostApi->allocations, sizeof(PaWinDsDeviceInfo) * deviceCount );
-        if( !winDsHostApi->winDsDeviceInfos )
-        {
-            result = paInsufficientMemory;
-            goto error;
-        }
-
-        for( i=0; i < deviceCount; ++i )
-        {
-            PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
-            deviceInfo->structVersion = 2;
-            deviceInfo->hostApi = hostApiIndex;
-            deviceInfo->name = 0;
-            (*hostApi)->deviceInfos[i] = deviceInfo;
-        }
-
-        for( i=0; i< inputNamesAndGUIDs.count; ++i )
-        {
-            result = AddInputDeviceInfoFromDirectSoundCapture( winDsHostApi,
-                    inputNamesAndGUIDs.items[i].name,
-                    inputNamesAndGUIDs.items[i].lpGUID );
-            if( result != paNoError )
-                goto error;
-        }
-
-        for( i=0; i< outputNamesAndGUIDs.count; ++i )
-        {
-            result = AddOutputDeviceInfoFromDirectSound( winDsHostApi,
-                    outputNamesAndGUIDs.items[i].name,
-                    outputNamesAndGUIDs.items[i].lpGUID );
-            if( result != paNoError )
-                goto error;
-        }
-    }    
-
-    result = TerminateDSDeviceNameAndGUIDVector( &inputNamesAndGUIDs );
-    if( result != paNoError )
-        goto error;
-
-    result = TerminateDSDeviceNameAndGUIDVector( &outputNamesAndGUIDs );
-    if( result != paNoError )
-        goto error;
-
-    
-    (*hostApi)->Terminate = Terminate;
-    (*hostApi)->OpenStream = OpenStream;
-    (*hostApi)->IsFormatSupported = IsFormatSupported;
-
-    PaUtil_InitializeStreamInterface( &winDsHostApi->callbackStreamInterface, CloseStream, StartStream,
-                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
-                                      GetStreamTime, GetStreamCpuLoad,
-                                      PaUtil_DummyRead, PaUtil_DummyWrite,
-                                      PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
-
-    PaUtil_InitializeStreamInterface( &winDsHostApi->blockingStreamInterface, CloseStream, StartStream,
-                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
-                                      GetStreamTime, PaUtil_DummyGetCpuLoad,
-                                      ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
-
-    return result;
-
-error:
-    if( winDsHostApi )
-    {
-        if( winDsHostApi->allocations )
-        {
-            PaUtil_FreeAllAllocations( winDsHostApi->allocations );
-            PaUtil_DestroyAllocationGroup( winDsHostApi->allocations );
-        }
-                
-        PaUtil_FreeMemory( winDsHostApi );
-    }
-
-    TerminateDSDeviceNameAndGUIDVector( &inputNamesAndGUIDs );
-    TerminateDSDeviceNameAndGUIDVector( &outputNamesAndGUIDs );
-
-    return result;
-}
-
-
-/***********************************************************************************/
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
-{
-    PaWinDsHostApiRepresentation *winDsHostApi = (PaWinDsHostApiRepresentation*)hostApi;
-
-    /*
-        IMPLEMENT ME:
-            - clean up any resources not handled by the allocation group
-    */
-
-    if( winDsHostApi->allocations )
-    {
-        PaUtil_FreeAllAllocations( winDsHostApi->allocations );
-        PaUtil_DestroyAllocationGroup( winDsHostApi->allocations );
-    }
-
-    PaUtil_FreeMemory( winDsHostApi );
-
-    PaWinDs_TerminateDSoundEntryPoints();
-
-    CoUninitialize();
-}
-
-
-/* Set minimal latency based on whether NT or Win95.
- * NT has higher latency.
- */
-static int PaWinDS_GetMinSystemLatency( void )
-{
-    int minLatencyMsec;
-    /* Set minimal latency based on whether NT or other OS.
-     * NT has higher latency.
-     */
-    OSVERSIONINFO osvi;
-	osvi.dwOSVersionInfoSize = sizeof( osvi );
-	GetVersionEx( &osvi );
-    DBUG(("PA - PlatformId = 0x%x\n", osvi.dwPlatformId ));
-    DBUG(("PA - MajorVersion = 0x%x\n", osvi.dwMajorVersion ));
-    DBUG(("PA - MinorVersion = 0x%x\n", osvi.dwMinorVersion ));
-    /* Check for NT */
-	if( (osvi.dwMajorVersion == 4) && (osvi.dwPlatformId == 2) )
-	{
-		minLatencyMsec = PA_WIN_NT_LATENCY;
-	}
-	else if(osvi.dwMajorVersion >= 5)
-	{
-		minLatencyMsec = PA_WIN_WDM_LATENCY;
-	}
-	else
-	{
-		minLatencyMsec = PA_WIN_9X_LATENCY;
-	}
-    return minLatencyMsec;
-}
-
-/***********************************************************************************/
-static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
-                                  const PaStreamParameters *inputParameters,
-                                  const PaStreamParameters *outputParameters,
-                                  double sampleRate )
-{
-    int inputChannelCount, outputChannelCount;
-    PaSampleFormat inputSampleFormat, outputSampleFormat;
-    
-    if( inputParameters )
-    {
-        inputChannelCount = inputParameters->channelCount;
-        inputSampleFormat = inputParameters->sampleFormat;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that input device can support inputChannelCount */
-        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
-            return paInvalidChannelCount;
-
-        /* validate inputStreamInfo */
-        if( inputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-    }
-    else
-    {
-        inputChannelCount = 0;
-    }
-
-    if( outputParameters )
-    {
-        outputChannelCount = outputParameters->channelCount;
-        outputSampleFormat = outputParameters->sampleFormat;
-        
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that output device can support inputChannelCount */
-        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
-            return paInvalidChannelCount;
-
-        /* validate outputStreamInfo */
-        if( outputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-    }
-    else
-    {
-        outputChannelCount = 0;
-    }
-    
-    /*
-        IMPLEMENT ME:
-
-            - if a full duplex stream is requested, check that the combination
-                of input and output parameters is supported if necessary
-
-            - check that the device supports sampleRate
-
-        Because the buffer adapter handles conversion between all standard
-        sample formats, the following checks are only required if paCustomFormat
-        is implemented, or under some other unusual conditions.
-
-            - check that input device can support inputSampleFormat, or that
-                we have the capability to convert from outputSampleFormat to
-                a native format
-
-            - check that output device can support outputSampleFormat, or that
-                we have the capability to convert from outputSampleFormat to
-                a native format
-    */
-
-    return paFormatIsSupported;
-}
-
-
-/*************************************************************************
-** Determine minimum number of buffers required for this host based
-** on minimum latency. Latency can be optionally set by user by setting
-** an environment variable. For example, to set latency to 200 msec, put:
-**
-**    set PA_MIN_LATENCY_MSEC=200
-**
-** in the AUTOEXEC.BAT file and reboot.
-** If the environment variable is not set, then the latency will be determined
-** based on the OS. Windows NT has higher latency than Win95.
-*/
-#define PA_LATENCY_ENV_NAME  ("PA_MIN_LATENCY_MSEC")
-#define PA_ENV_BUF_SIZE  (32)
-
-static int PaWinDs_GetMinLatencyFrames( double sampleRate )
-{
-    char      envbuf[PA_ENV_BUF_SIZE];
-    DWORD     hresult;
-    int       minLatencyMsec = 0;
-
-    /* Let user determine minimal latency by setting environment variable. */
-    hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE );
-    if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) )
-    {
-        minLatencyMsec = atoi( envbuf );
-    }
-    else
-    {
-        minLatencyMsec = PaWinDS_GetMinSystemLatency();
-#if PA_USE_HIGH_LATENCY
-        PRINT(("PA - Minimum Latency set to %d msec!\n", minLatencyMsec ));
-#endif
-
-    }
-
-    return (int) (minLatencyMsec * sampleRate * SECONDS_PER_MSEC);
-}
-
-
-static HRESULT InitInputBuffer( PaWinDsStream *stream, unsigned long nFrameRate, WORD nChannels, int bytesPerBuffer )
-{
-    DSCBUFFERDESC  captureDesc;
-    WAVEFORMATEX   wfFormat;
-    HRESULT        result;
-    
-    stream->bytesPerInputFrame = nChannels * sizeof(short);
-
-    // Define the buffer format
-    wfFormat.wFormatTag      = WAVE_FORMAT_PCM;
-    wfFormat.nChannels       = nChannels;
-    wfFormat.nSamplesPerSec  = nFrameRate;
-    wfFormat.wBitsPerSample  = 8 * sizeof(short);
-    wfFormat.nBlockAlign     = (WORD)(wfFormat.nChannels * (wfFormat.wBitsPerSample / 8));
-    wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;
-    wfFormat.cbSize          = 0;   /* No extended format info. */
-    stream->inputSize = bytesPerBuffer;
-    // ----------------------------------------------------------------------
-    // Setup the secondary buffer description
-    ZeroMemory(&captureDesc, sizeof(DSCBUFFERDESC));
-    captureDesc.dwSize = sizeof(DSCBUFFERDESC);
-    captureDesc.dwFlags =  0;
-    captureDesc.dwBufferBytes = bytesPerBuffer;
-    captureDesc.lpwfxFormat = &wfFormat;
-    // Create the capture buffer
-    if ((result = IDirectSoundCapture_CreateCaptureBuffer( stream->pDirectSoundCapture,
-                  &captureDesc, &stream->pDirectSoundInputBuffer, NULL)) != DS_OK) return result;
-    stream->readOffset = 0;  // reset last read position to start of buffer
-    return DS_OK;
-}
-
-
-static HRESULT InitOutputBuffer( PaWinDsStream *stream, unsigned long nFrameRate, WORD nChannels, int bytesPerBuffer )
-{
-    DWORD          dwDataLen;
-    DWORD          playCursor;
-    HRESULT        result;
-    LPDIRECTSOUNDBUFFER pPrimaryBuffer;
-    HWND           hWnd;
-    HRESULT        hr;
-    WAVEFORMATEX   wfFormat;
-    DSBUFFERDESC   primaryDesc;
-    DSBUFFERDESC   secondaryDesc;
-    unsigned char* pDSBuffData;
-    LARGE_INTEGER  counterFrequency;
-
-    stream->outputBufferSizeBytes = bytesPerBuffer;
-    stream->outputIsRunning = FALSE;
-    stream->outputUnderflowCount = 0;
-    stream->dsw_framesWritten = 0;
-    stream->bytesPerOutputFrame = nChannels * sizeof(short);
-
-    // We were using getForegroundWindow() but sometimes the ForegroundWindow may not be the
-    // applications's window. Also if that window is closed before the Buffer is closed
-    // then DirectSound can crash. (Thanks for Scott Patterson for reporting this.)
-    // So we will use GetDesktopWindow() which was suggested by Miller Puckette.
-    // hWnd = GetForegroundWindow();
-    //
-    //  FIXME: The example code I have on the net creates a hidden window that
-    //      is managed by our code - I think we should do that - one hidden
-    //      window for the whole of Pa_DS
-    //
-    hWnd = GetDesktopWindow();
-
-    // Set cooperative level to DSSCL_EXCLUSIVE so that we can get 16 bit output, 44.1 KHz.
-    // Exclusize also prevents unexpected sounds from other apps during a performance.
-    if ((hr = IDirectSound_SetCooperativeLevel( stream->pDirectSound,
-              hWnd, DSSCL_EXCLUSIVE)) != DS_OK)
-    {
-        return hr;
-    }
-
-    // -----------------------------------------------------------------------
-    // Create primary buffer and set format just so we can specify our custom format.
-    // Otherwise we would be stuck with the default which might be 8 bit or 22050 Hz.
-    // Setup the primary buffer description
-    ZeroMemory(&primaryDesc, sizeof(DSBUFFERDESC));
-    primaryDesc.dwSize        = sizeof(DSBUFFERDESC);
-    primaryDesc.dwFlags       = DSBCAPS_PRIMARYBUFFER; // all panning, mixing, etc done by synth
-    primaryDesc.dwBufferBytes = 0;
-    primaryDesc.lpwfxFormat   = NULL;
-    // Create the buffer
-    if ((result = IDirectSound_CreateSoundBuffer( stream->pDirectSound,
-                  &primaryDesc, &pPrimaryBuffer, NULL)) != DS_OK) return result;
-    // Define the buffer format
-    wfFormat.wFormatTag = WAVE_FORMAT_PCM;
-    wfFormat.nChannels = nChannels;
-    wfFormat.nSamplesPerSec = nFrameRate;
-    wfFormat.wBitsPerSample = 8 * sizeof(short);
-    wfFormat.nBlockAlign = (WORD)(wfFormat.nChannels * (wfFormat.wBitsPerSample / 8));
-    wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;
-    wfFormat.cbSize = 0;  /* No extended format info. */
-    // Set the primary buffer's format
-    if((result = IDirectSoundBuffer_SetFormat( pPrimaryBuffer, &wfFormat)) != DS_OK) return result;
-
-    // ----------------------------------------------------------------------
-    // Setup the secondary buffer description
-    ZeroMemory(&secondaryDesc, sizeof(DSBUFFERDESC));
-    secondaryDesc.dwSize = sizeof(DSBUFFERDESC);
-    secondaryDesc.dwFlags =  DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
-    secondaryDesc.dwBufferBytes = bytesPerBuffer;
-    secondaryDesc.lpwfxFormat = &wfFormat;
-    // Create the secondary buffer
-    if ((result = IDirectSound_CreateSoundBuffer( stream->pDirectSound,
-                  &secondaryDesc, &stream->pDirectSoundOutputBuffer, NULL)) != DS_OK) return result;
-    // Lock the DS buffer
-    if ((result = IDirectSoundBuffer_Lock( stream->pDirectSoundOutputBuffer, 0, stream->outputBufferSizeBytes, (LPVOID*)&pDSBuffData,
-                                           &dwDataLen, NULL, 0, 0)) != DS_OK) return result;
-    // Zero the DS buffer
-    ZeroMemory(pDSBuffData, dwDataLen);
-    // Unlock the DS buffer
-    if ((result = IDirectSoundBuffer_Unlock( stream->pDirectSoundOutputBuffer, pDSBuffData, dwDataLen, NULL, 0)) != DS_OK) return result;
-    if( QueryPerformanceFrequency( &counterFrequency ) )
-    {
-        int framesInBuffer = bytesPerBuffer / (nChannels * sizeof(short));
-        stream->perfCounterTicksPerBuffer.QuadPart = (counterFrequency.QuadPart * framesInBuffer) / nFrameRate;
-    }
-    else
-    {
-        stream->perfCounterTicksPerBuffer.QuadPart = 0;
-    }
-    // Let DSound set the starting write position because if we set it to zero, it looks like the
-    // buffer is full to begin with. This causes a long pause before sound starts when using large buffers.
-    hr = IDirectSoundBuffer_GetCurrentPosition( stream->pDirectSoundOutputBuffer,
-            &playCursor, &stream->outputBufferWriteOffsetBytes );
-    if( hr != DS_OK )
-    {
-        return hr;
-    }
-    stream->dsw_framesWritten = stream->outputBufferWriteOffsetBytes / stream->bytesPerOutputFrame;
-    /* printf("DSW_InitOutputBuffer: playCursor = %d, writeCursor = %d\n", playCursor, dsw->dsw_WriteOffset ); */
-    return DS_OK;
-}
-
-
-/***********************************************************************************/
-/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
-
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
-                           PaStream** s,
-                           const PaStreamParameters *inputParameters,
-                           const PaStreamParameters *outputParameters,
-                           double sampleRate,
-                           unsigned long framesPerBuffer,
-                           PaStreamFlags streamFlags,
-                           PaStreamCallback *streamCallback,
-                           void *userData )
-{
-    PaError result = paNoError;
-    PaWinDsHostApiRepresentation *winDsHostApi = (PaWinDsHostApiRepresentation*)hostApi;
-    PaWinDsStream *stream = 0;
-    int inputChannelCount, outputChannelCount;
-    PaSampleFormat inputSampleFormat, outputSampleFormat;
-    PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
-    unsigned long suggestedInputLatencyFrames, suggestedOutputLatencyFrames;
-
-    if( inputParameters )
-    {
-        inputChannelCount = inputParameters->channelCount;
-        inputSampleFormat = inputParameters->sampleFormat;
-        suggestedInputLatencyFrames = (unsigned long)(inputParameters->suggestedLatency * sampleRate);
-
-        /* IDEA: the following 3 checks could be performed by default by pa_front
-            unless some flag indicated otherwise */
-            
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that input device can support inputChannelCount */
-        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
-            return paInvalidChannelCount;
-            
-        /* validate hostApiSpecificStreamInfo */
-        if( inputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-    }
-    else
-    {
-        inputChannelCount = 0;
-		inputSampleFormat = 0;
-        suggestedInputLatencyFrames = 0;
-    }
-
-
-    if( outputParameters )
-    {
-        outputChannelCount = outputParameters->channelCount;
-        outputSampleFormat = outputParameters->sampleFormat;
-        suggestedOutputLatencyFrames = (unsigned long)(outputParameters->suggestedLatency * sampleRate);
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that output device can support inputChannelCount */
-        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
-            return paInvalidChannelCount;
-
-        /* validate hostApiSpecificStreamInfo */
-        if( outputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */            
-    }
-    else
-    {
-        outputChannelCount = 0;
-		outputSampleFormat = 0;
-        suggestedOutputLatencyFrames = 0;
-    }
-
-
-    /*
-        IMPLEMENT ME:
-
-        ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() )
-
-            - check that input device can support inputSampleFormat, or that
-                we have the capability to convert from outputSampleFormat to
-                a native format
-
-            - check that output device can support outputSampleFormat, or that
-                we have the capability to convert from outputSampleFormat to
-                a native format
-
-            - if a full duplex stream is requested, check that the combination
-                of input and output parameters is supported
-
-            - check that the device supports sampleRate
-
-            - alter sampleRate to a close allowable rate if possible / necessary
-
-            - validate suggestedInputLatency and suggestedOutputLatency parameters,
-                use default values where necessary
-    */
-
-
-    /* validate platform specific flags */
-    if( (streamFlags & paPlatformSpecificFlags) != 0 )
-        return paInvalidFlag; /* unexpected platform specific flag */
-
-
-    stream = (PaWinDsStream*)PaUtil_AllocateMemory( sizeof(PaWinDsStream) );
-    if( !stream )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    memset( stream, 0, sizeof(PaWinDsStream) ); /* initialize all stream variables to 0 */
-
-    if( streamCallback )
-    {
-        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
-                                               &winDsHostApi->callbackStreamInterface, streamCallback, userData );
-    }
-    else
-    {
-        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
-                                               &winDsHostApi->blockingStreamInterface, streamCallback, userData );
-    }
-    
-    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
-
-
-    if( inputParameters )
-    {
-        /* IMPLEMENT ME - establish which  host formats are available */
-        hostInputSampleFormat =
-            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputParameters->sampleFormat );
-    }
-	else
-	{
-		hostInputSampleFormat = 0;
-	}
-
-    if( outputParameters )
-    {
-        /* IMPLEMENT ME - establish which  host formats are available */
-        hostOutputSampleFormat =
-            PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputParameters->sampleFormat );
-    }
-    else
-	{
-		hostOutputSampleFormat = 0;
-	}
-
-    result =  PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
-                    inputChannelCount, inputSampleFormat, hostInputSampleFormat,
-                    outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
-                    sampleRate, streamFlags, framesPerBuffer,
-                    framesPerBuffer, /* ignored in paUtilVariableHostBufferSizePartialUsageAllowed mode. */
-                /* This next mode is required because DS can split the host buffer when it wraps around. */
-                    paUtilVariableHostBufferSizePartialUsageAllowed,
-                    streamCallback, userData );
-    if( result != paNoError )
-        goto error;
-
-
-    stream->streamRepresentation.streamInfo.inputLatency =
-            PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor);   /* FIXME: not initialised anywhere else */
-    stream->streamRepresentation.streamInfo.outputLatency =
-            PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor);    /* FIXME: not initialised anywhere else */
-    stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
-
-    
-/* DirectSound specific initialization */ 
-    {
-        HRESULT          hr;
-        int              bytesPerDirectSoundBuffer;
-        int              userLatencyFrames;
-        int              minLatencyFrames;
-
-        stream->timerID = 0;
-
-    /* Get system minimum latency. */
-        minLatencyFrames = PaWinDs_GetMinLatencyFrames( sampleRate );
-
-    /* Let user override latency by passing latency parameter. */
-        userLatencyFrames = (suggestedInputLatencyFrames > suggestedOutputLatencyFrames)
-                    ? suggestedInputLatencyFrames
-                    : suggestedOutputLatencyFrames;
-        if( userLatencyFrames > 0 ) minLatencyFrames = userLatencyFrames;
-
-    /* Calculate stream->framesPerDSBuffer depending on framesPerBuffer */
-        if( framesPerBuffer == paFramesPerBufferUnspecified )
-        {
-        /* App support variable framesPerBuffer */
-            stream->framesPerDSBuffer = minLatencyFrames;
-
-            stream->streamRepresentation.streamInfo.outputLatency = (double)(minLatencyFrames - 1) / sampleRate;
-        }
-        else
-        {
-        /* Round up to number of buffers needed to guarantee that latency. */
-            int numUserBuffers = (minLatencyFrames + framesPerBuffer - 1) / framesPerBuffer;
-            if( numUserBuffers < 1 ) numUserBuffers = 1;
-            numUserBuffers += 1; /* So we have latency worth of buffers ahead of current buffer. */
-            stream->framesPerDSBuffer = framesPerBuffer * numUserBuffers;
-
-            stream->streamRepresentation.streamInfo.outputLatency = (double)(framesPerBuffer * (numUserBuffers-1)) / sampleRate;
-        }
-
-        {
-            /** @todo REVIEW: this calculation seems incorrect to me - rossb. */
-            int msecLatency = (int) ((stream->framesPerDSBuffer * MSEC_PER_SECOND) / sampleRate);
-            PRINT(("PortAudio on DirectSound - Latency = %d frames, %d msec\n", stream->framesPerDSBuffer, msecLatency ));
-        }
-
-
-        /* ------------------ OUTPUT */
-        if( outputParameters )
-        {
-            /*
-            PaDeviceInfo *deviceInfo = hostApi->deviceInfos[ outputParameters->device ];
-            DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", outputParameters->device));
-            */
-            
-            bytesPerDirectSoundBuffer = stream->framesPerDSBuffer * outputParameters->channelCount * sizeof(short);
-            if( bytesPerDirectSoundBuffer < DSBSIZE_MIN )
-            {
-                result = paBufferTooSmall;
-                goto error;
-            }
-            else if( bytesPerDirectSoundBuffer > DSBSIZE_MAX )
-            {
-                result = paBufferTooBig;
-                goto error;
-            }
-
-
-            hr = paWinDsDSoundEntryPoints.DirectSoundCreate( winDsHostApi->winDsDeviceInfos[outputParameters->device].lpGUID,
-                        &stream->pDirectSound, NULL );
-            if( hr != DS_OK )
-            {
-                ERR_RPT(("PortAudio: DirectSoundCreate() failed!\n"));
-                result = paUnanticipatedHostError;
-                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );
-                goto error;
-            }
-            hr = InitOutputBuffer( stream,
-                                       (unsigned long) (sampleRate + 0.5),
-                                       (WORD)outputParameters->channelCount, bytesPerDirectSoundBuffer );
-            DBUG(("InitOutputBuffer() returns %x\n", hr));
-            if( hr != DS_OK )
-            {
-                result = paUnanticipatedHostError;
-                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );
-                goto error;
-            }
-            /* Calculate value used in latency calculation to avoid real-time divides. */
-            stream->secondsPerHostByte = 1.0 /
-                (stream->bufferProcessor.bytesPerHostOutputSample *
-                outputChannelCount * sampleRate);
-        }
-
-        /* ------------------ INPUT */
-        if( inputParameters )
-        {
-            /*
-            PaDeviceInfo *deviceInfo = hostApi->deviceInfos[ inputParameters->device ];
-            DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", inputParameters->device));
-            */
-            
-            bytesPerDirectSoundBuffer = stream->framesPerDSBuffer * inputParameters->channelCount * sizeof(short);
-            if( bytesPerDirectSoundBuffer < DSBSIZE_MIN )
-            {
-                result = paBufferTooSmall;
-                goto error;
-            }
-            else if( bytesPerDirectSoundBuffer > DSBSIZE_MAX )
-            {
-                result = paBufferTooBig;
-                goto error;
-            }
-
-            hr = paWinDsDSoundEntryPoints.DirectSoundCaptureCreate( winDsHostApi->winDsDeviceInfos[inputParameters->device].lpGUID,
-                        &stream->pDirectSoundCapture,   NULL );
-            if( hr != DS_OK )
-            {
-                ERR_RPT(("PortAudio: DirectSoundCaptureCreate() failed!\n"));
-                result = paUnanticipatedHostError;
-                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );
-                goto error;
-            }
-            hr = InitInputBuffer( stream,
-                                      (unsigned long) (sampleRate + 0.5),
-                                      (WORD)inputParameters->channelCount, bytesPerDirectSoundBuffer );
-            DBUG(("InitInputBuffer() returns %x\n", hr));
-            if( hr != DS_OK )
-            {
-                ERR_RPT(("PortAudio: DSW_InitInputBuffer() returns %x\n", hr));
-                result = paUnanticipatedHostError;
-                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );
-                goto error;
-            }
-        }
-
-    }
-
-    *s = (PaStream*)stream;
-
-    return result;
-
-error:
-    if( stream )
-        PaUtil_FreeMemory( stream );
-
-    return result;
-}
-
-
-/************************************************************************************
- * Determine how much space can be safely written to in DS buffer.
- * Detect underflows and overflows.
- * Does not allow writing into safety gap maintained by DirectSound.
- */
-static HRESULT QueryOutputSpace( PaWinDsStream *stream, long *bytesEmpty )
-{
-    HRESULT hr;
-    DWORD   playCursor;
-    DWORD   writeCursor;
-    long    numBytesEmpty;
-    long    playWriteGap;
-    // Query to see how much room is in buffer.
-    hr = IDirectSoundBuffer_GetCurrentPosition( stream->pDirectSoundOutputBuffer,
-            &playCursor, &writeCursor );
-    if( hr != DS_OK )
-    {
-        return hr;
-    }
-    // Determine size of gap between playIndex and WriteIndex that we cannot write into.
-    playWriteGap = writeCursor - playCursor;
-    if( playWriteGap < 0 ) playWriteGap += stream->outputBufferSizeBytes; // unwrap
-    /* DirectSound doesn't have a large enough playCursor so we cannot detect wrap-around. */
-    /* Attempt to detect playCursor wrap-around and correct it. */
-    if( stream->outputIsRunning && (stream->perfCounterTicksPerBuffer.QuadPart != 0) )
-    {
-        /* How much time has elapsed since last check. */
-        LARGE_INTEGER   currentTime;
-        LARGE_INTEGER   elapsedTime;
-        long            bytesPlayed;
-        long            bytesExpected;
-        long            buffersWrapped;
-        QueryPerformanceCounter( &currentTime );
-        elapsedTime.QuadPart = currentTime.QuadPart - stream->previousPlayTime.QuadPart;
-        stream->previousPlayTime = currentTime;
-        /* How many bytes does DirectSound say have been played. */
-        bytesPlayed = playCursor - stream->previousPlayCursor;
-        if( bytesPlayed < 0 ) bytesPlayed += stream->outputBufferSizeBytes; // unwrap
-        stream->previousPlayCursor = playCursor;
-        /* Calculate how many bytes we would have expected to been played by now. */
-        bytesExpected = (long) ((elapsedTime.QuadPart * stream->outputBufferSizeBytes) / stream->perfCounterTicksPerBuffer.QuadPart);
-        buffersWrapped = (bytesExpected - bytesPlayed) / stream->outputBufferSizeBytes;
-        if( buffersWrapped > 0 )
-        {
-            playCursor += (buffersWrapped * stream->outputBufferSizeBytes);
-            bytesPlayed += (buffersWrapped * stream->outputBufferSizeBytes);
-        }
-        /* Maintain frame output cursor. */
-        stream->framesPlayed += (bytesPlayed / stream->bytesPerOutputFrame);
-    }
-    numBytesEmpty = playCursor - stream->outputBufferWriteOffsetBytes;
-    if( numBytesEmpty < 0 ) numBytesEmpty += stream->outputBufferSizeBytes; // unwrap offset
-    /* Have we underflowed? */
-    if( numBytesEmpty > (stream->outputBufferSizeBytes - playWriteGap) )
-    {
-        if( stream->outputIsRunning )
-        {
-            stream->outputUnderflowCount += 1;
-        }
-        stream->outputBufferWriteOffsetBytes = writeCursor;
-        numBytesEmpty = stream->outputBufferSizeBytes - playWriteGap;
-    }
-    *bytesEmpty = numBytesEmpty;
-    return hr;
-}
-
-/***********************************************************************************/
-static PaError Pa_TimeSlice( PaWinDsStream *stream )
-{
-    PaError           result = 0;   /* FIXME: this should be declared int and this function should also return that type (same as stream callback return type)*/
-    long              numFrames = 0;
-    long              bytesEmpty = 0;
-    long              bytesFilled = 0;
-    long              bytesToXfer = 0;
-    long              framesToXfer = 0;
-    long              numInFramesReady = 0;
-    long              numOutFramesReady = 0;
-    long              bytesProcessed;
-    HRESULT           hresult;
-    double            outputLatency = 0;
-    PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /** @todo implement inputBufferAdcTime */
-    
-/* Input */
-    LPBYTE            lpInBuf1 = NULL;
-    LPBYTE            lpInBuf2 = NULL;
-    DWORD             dwInSize1 = 0;
-    DWORD             dwInSize2 = 0;
-/* Output */
-    LPBYTE            lpOutBuf1 = NULL;
-    LPBYTE            lpOutBuf2 = NULL;
-    DWORD             dwOutSize1 = 0;
-    DWORD             dwOutSize2 = 0;
-
-    /* How much input data is available? */
-    if( stream->bufferProcessor.inputChannelCount > 0 )
-    {
-        HRESULT hr;
-        DWORD capturePos;
-        DWORD readPos;
-        long  filled = 0;
-        // Query to see how much data is in buffer.
-        // We don't need the capture position but sometimes DirectSound doesn't handle NULLS correctly
-        // so let's pass a pointer just to be safe.
-        hr = IDirectSoundCaptureBuffer_GetCurrentPosition( stream->pDirectSoundInputBuffer, &capturePos, &readPos );
-        if( hr == DS_OK )
-        {
-            filled = readPos - stream->readOffset;
-            if( filled < 0 ) filled += stream->inputSize; // unwrap offset
-            bytesFilled = filled;
-        }
-            // FIXME: what happens if IDirectSoundCaptureBuffer_GetCurrentPosition fails?
-
-        framesToXfer = numInFramesReady = bytesFilled / stream->bytesPerInputFrame;
-        outputLatency = ((double)bytesFilled) * stream->secondsPerHostByte;
-
-        /** @todo Check for overflow */
-    }
-
-    /* How much output room is available? */
-    if( stream->bufferProcessor.outputChannelCount > 0 )
-    {
-        UINT previousUnderflowCount = stream->outputUnderflowCount;
-        QueryOutputSpace( stream, &bytesEmpty );
-        framesToXfer = numOutFramesReady = bytesEmpty / stream->bytesPerOutputFrame;
-
-        /* Check for underflow */
-        if( stream->outputUnderflowCount != previousUnderflowCount )
-            stream->callbackFlags |= paOutputUnderflow;
-    }
-
-    if( (numInFramesReady > 0) && (numOutFramesReady > 0) )
-    {
-        framesToXfer = (numOutFramesReady < numInFramesReady) ? numOutFramesReady : numInFramesReady;
-    }
-
-    if( framesToXfer > 0 )
-    {
-
-        PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
-
-    /* The outputBufferDacTime parameter should indicates the time at which
-        the first sample of the output buffer is heard at the DACs. */
-        timeInfo.currentTime = PaUtil_GetTime();
-        timeInfo.outputBufferDacTime = timeInfo.currentTime + outputLatency;
-
-
-        PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, stream->callbackFlags );
-        stream->callbackFlags = 0;
-        
-    /* Input */
-        if( stream->bufferProcessor.inputChannelCount > 0 )
-        {
-            bytesToXfer = framesToXfer * stream->bytesPerInputFrame;
-            hresult = IDirectSoundCaptureBuffer_Lock ( stream->pDirectSoundInputBuffer,
-                stream->readOffset, bytesToXfer,
-                (void **) &lpInBuf1, &dwInSize1,
-                (void **) &lpInBuf2, &dwInSize2, 0);
-            if (hresult != DS_OK)
-            {
-                ERR_RPT(("DirectSound IDirectSoundCaptureBuffer_Lock failed, hresult = 0x%x\n",hresult));
-                result = paUnanticipatedHostError;
-                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hresult );
-                goto error2;
-            }
-
-            numFrames = dwInSize1 / stream->bytesPerInputFrame;
-            PaUtil_SetInputFrameCount( &stream->bufferProcessor, numFrames );
-            PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, 0, lpInBuf1, 0 );
-        /* Is input split into two regions. */
-            if( dwInSize2 > 0 )
-            {
-                numFrames = dwInSize2 / stream->bytesPerInputFrame;
-                PaUtil_Set2ndInputFrameCount( &stream->bufferProcessor, numFrames );
-                PaUtil_Set2ndInterleavedInputChannels( &stream->bufferProcessor, 0, lpInBuf2, 0 );
-            }
-        }
-
-    /* Output */
-        if( stream->bufferProcessor.outputChannelCount > 0 )
-        {
-            bytesToXfer = framesToXfer * stream->bytesPerOutputFrame;
-            hresult = IDirectSoundBuffer_Lock ( stream->pDirectSoundOutputBuffer,
-                stream->outputBufferWriteOffsetBytes, bytesToXfer,
-                (void **) &lpOutBuf1, &dwOutSize1,
-                (void **) &lpOutBuf2, &dwOutSize2, 0);
-            if (hresult != DS_OK)
-            {
-                ERR_RPT(("DirectSound IDirectSoundBuffer_Lock failed, hresult = 0x%x\n",hresult));
-                result = paUnanticipatedHostError;
-                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hresult );
-                goto error1;
-            }
-
-            numFrames = dwOutSize1 / stream->bytesPerOutputFrame;
-            PaUtil_SetOutputFrameCount( &stream->bufferProcessor, numFrames );
-            PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, 0, lpOutBuf1, 0 );
-
-        /* Is output split into two regions. */
-            if( dwOutSize2 > 0 )
-            {
-                numFrames = dwOutSize2 / stream->bytesPerOutputFrame;
-                PaUtil_Set2ndOutputFrameCount( &stream->bufferProcessor, numFrames );
-                PaUtil_Set2ndInterleavedOutputChannels( &stream->bufferProcessor, 0, lpOutBuf2, 0 );
-            }
-        }
-
-        result = paContinue;
-        numFrames = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &result );
-        stream->framesWritten += numFrames;
-        
-        if( stream->bufferProcessor.outputChannelCount > 0 )
-        {
-        /* FIXME: an underflow could happen here */
-
-        /* Update our buffer offset and unlock sound buffer */
-            bytesProcessed = numFrames * stream->bytesPerOutputFrame;
-            stream->outputBufferWriteOffsetBytes = (stream->outputBufferWriteOffsetBytes + bytesProcessed) % stream->outputBufferSizeBytes;
-            IDirectSoundBuffer_Unlock( stream->pDirectSoundOutputBuffer, lpOutBuf1, dwOutSize1, lpOutBuf2, dwOutSize2);
-            stream->dsw_framesWritten += numFrames;
-        }
-
-error1:
-        if( stream->bufferProcessor.inputChannelCount > 0 )
-        {
-        /* FIXME: an overflow could happen here */
-
-        /* Update our buffer offset and unlock sound buffer */
-            bytesProcessed = numFrames * stream->bytesPerInputFrame;
-            stream->readOffset = (stream->readOffset + bytesProcessed) % stream->inputSize;
-            IDirectSoundCaptureBuffer_Unlock( stream->pDirectSoundInputBuffer, lpInBuf1, dwInSize1, lpInBuf2, dwInSize2);
-        }
-error2:
-
-        PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, numFrames );
-
-    }
-    
-    return result;
-}
-/*******************************************************************/
-
-static HRESULT ZeroAvailableOutputSpace( PaWinDsStream *stream )
-{
-    HRESULT hr;
-    LPBYTE lpbuf1 = NULL;
-    LPBYTE lpbuf2 = NULL;
-    DWORD dwsize1 = 0;
-    DWORD dwsize2 = 0;
-    long  bytesEmpty;
-    hr = QueryOutputSpace( stream, &bytesEmpty ); // updates framesPlayed
-    if (hr != DS_OK) return hr;
-    if( bytesEmpty == 0 ) return DS_OK;
-    // Lock free space in the DS
-    hr = IDirectSoundBuffer_Lock( stream->pDirectSoundOutputBuffer, stream->outputBufferWriteOffsetBytes,
-                                    bytesEmpty, (void **) &lpbuf1, &dwsize1,
-                                    (void **) &lpbuf2, &dwsize2, 0);
-    if (hr == DS_OK)
-    {
-        // Copy the buffer into the DS
-        ZeroMemory(lpbuf1, dwsize1);
-        if(lpbuf2 != NULL)
-        {
-            ZeroMemory(lpbuf2, dwsize2);
-        }
-        // Update our buffer offset and unlock sound buffer
-        stream->outputBufferWriteOffsetBytes = (stream->outputBufferWriteOffsetBytes + dwsize1 + dwsize2) % stream->outputBufferSizeBytes;
-        IDirectSoundBuffer_Unlock( stream->pDirectSoundOutputBuffer, lpbuf1, dwsize1, lpbuf2, dwsize2);
-        stream->dsw_framesWritten += bytesEmpty / stream->bytesPerOutputFrame;
-    }
-    return hr;
-}
-
-
-static void CALLBACK Pa_TimerCallback(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD dw1, DWORD dw2)
-{
-    PaWinDsStream *stream;
-
-    /* suppress unused variable warnings */
-    (void) uID;
-    (void) uMsg;
-    (void) dw1;
-    (void) dw2;
-    
-    stream = (PaWinDsStream *) dwUser;
-    if( stream == NULL ) return;
-
-    if( stream->isActive )
-    {
-        if( stream->abortProcessing )
-        {
-            stream->isActive = 0;
-        }
-        else if( stream->stopProcessing )
-        {
-            if( stream->bufferProcessor.outputChannelCount > 0 )
-            {
-                ZeroAvailableOutputSpace( stream );
-                /* clear isActive when all sound played */
-                if( stream->framesPlayed >= stream->framesWritten )
-                {
-                    stream->isActive = 0;
-                }
-            }
-            else
-            {
-                stream->isActive = 0;
-            }
-        }
-        else
-        {
-            if( Pa_TimeSlice( stream ) != 0)  /* Call time slice independant of timing method. */
-            {
-                /* FIXME implement handling of paComplete and paAbort if possible */
-                stream->stopProcessing = 1;
-            }
-        }
-
-        if( !stream->isActive ){
-            if( stream->streamRepresentation.streamFinishedCallback != 0 )
-                stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
-        }
-    }
-}
-
-/***********************************************************************************
-    When CloseStream() is called, the multi-api layer ensures that
-    the stream has already been stopped or aborted.
-*/
-static PaError CloseStream( PaStream* s )
-{
-    PaError result = paNoError;
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    // Cleanup the sound buffers
-    if( stream->pDirectSoundOutputBuffer )
-    {
-        IDirectSoundBuffer_Stop( stream->pDirectSoundOutputBuffer );
-        IDirectSoundBuffer_Release( stream->pDirectSoundOutputBuffer );
-        stream->pDirectSoundOutputBuffer = NULL;
-    }
-
-    if( stream->pDirectSoundInputBuffer )
-    {
-        IDirectSoundCaptureBuffer_Stop( stream->pDirectSoundInputBuffer );
-        IDirectSoundCaptureBuffer_Release( stream->pDirectSoundInputBuffer );
-        stream->pDirectSoundInputBuffer = NULL;
-    }
-
-    if( stream->pDirectSoundCapture )
-    {
-        IDirectSoundCapture_Release( stream->pDirectSoundCapture );
-        stream->pDirectSoundCapture = NULL;
-    }
-
-    if( stream->pDirectSound )
-    {
-        IDirectSound_Release( stream->pDirectSound );
-        stream->pDirectSound = NULL;
-    }
-
-    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
-    PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
-    PaUtil_FreeMemory( stream );
-
-    return result;
-}
-
-/***********************************************************************************/
-static PaError StartStream( PaStream *s )
-{
-    PaError          result = paNoError;
-    PaWinDsStream   *stream = (PaWinDsStream*)s;
-    HRESULT          hr;
-
-    PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
-    
-    if( stream->bufferProcessor.inputChannelCount > 0 )
-    {
-        // Start the buffer playback
-        if( stream->pDirectSoundInputBuffer != NULL ) // FIXME: not sure this check is necessary
-        {
-            hr = IDirectSoundCaptureBuffer_Start( stream->pDirectSoundInputBuffer, DSCBSTART_LOOPING );
-        }
-
-        DBUG(("StartStream: DSW_StartInput returned = 0x%X.\n", hr));
-        if( hr != DS_OK )
-        {
-            result = paUnanticipatedHostError;
-            PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );
-            goto error;
-        }
-    }
-
-    stream->framesWritten = 0;
-    stream->callbackFlags = 0;
-
-    stream->abortProcessing = 0;
-    stream->stopProcessing = 0;
-    stream->isActive = 1;
-
-    if( stream->bufferProcessor.outputChannelCount > 0 )
-    {
-        /* Give user callback a chance to pre-fill buffer. REVIEW - i thought we weren't pre-filling, rb. */
-        result = Pa_TimeSlice( stream );
-        if( result != paNoError ) return result; // FIXME - what if finished?
-
-        QueryPerformanceCounter( &stream->previousPlayTime );
-        stream->previousPlayCursor = 0;
-        stream->framesPlayed = 0;
-        hr = IDirectSoundBuffer_SetCurrentPosition( stream->pDirectSoundOutputBuffer, 0 );
-        DBUG(("PaHost_StartOutput: IDirectSoundBuffer_SetCurrentPosition returned = 0x%X.\n", hr));
-        if( hr != DS_OK )
-        {
-            result = paUnanticipatedHostError;
-            PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );
-            goto error;
-        }
-
-        // Start the buffer playback in a loop.
-        if( stream->pDirectSoundOutputBuffer != NULL ) // FIXME: not sure this needs to be checked here
-        {
-            hr = IDirectSoundBuffer_Play( stream->pDirectSoundOutputBuffer, 0, 0, DSBPLAY_LOOPING );
-            DBUG(("PaHost_StartOutput: IDirectSoundBuffer_Play returned = 0x%X.\n", hr));
-            if( hr != DS_OK )
-            {
-                result = paUnanticipatedHostError;
-                PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );
-                goto error;
-            }
-            stream->outputIsRunning = TRUE;
-        }
-    }
-
-
-    /* Create timer that will wake us up so we can fill the DSound buffer. */
-    {
-        int resolution;
-        int framesPerWakeup = stream->framesPerDSBuffer / 4;
-        int msecPerWakeup = MSEC_PER_SECOND * framesPerWakeup / (int) stream->streamRepresentation.streamInfo.sampleRate;
-        if( msecPerWakeup < 10 ) msecPerWakeup = 10;
-        else if( msecPerWakeup > 100 ) msecPerWakeup = 100;
-        resolution = msecPerWakeup/4;
-        stream->timerID = timeSetEvent( msecPerWakeup, resolution, (LPTIMECALLBACK) Pa_TimerCallback,
-                                             (DWORD_PTR) stream, TIME_PERIODIC );
-    }
-    if( stream->timerID == 0 )
-    {
-        stream->isActive = 0;
-        result = paUnanticipatedHostError;
-        PA_DS_SET_LAST_DIRECTSOUND_ERROR( hr );
-        goto error;
-    }
-
-    stream->isStarted = TRUE;
-
-error:
-    return result;
-}
-
-
-/***********************************************************************************/
-static PaError StopStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-    HRESULT          hr;
-    int timeoutMsec;
-
-    stream->stopProcessing = 1;
-    /* Set timeout at 20% beyond maximum time we might wait. */
-    timeoutMsec = (int) (1200.0 * stream->framesPerDSBuffer / stream->streamRepresentation.streamInfo.sampleRate);
-    while( stream->isActive && (timeoutMsec > 0)  )
-    {
-        Sleep(10);
-        timeoutMsec -= 10;
-    }
-    if( stream->timerID != 0 )
-    {
-        timeKillEvent(stream->timerID);  /* Stop callback timer. */
-        stream->timerID = 0;
-    }
-
-
-    if( stream->bufferProcessor.outputChannelCount > 0 )
-    {
-        // Stop the buffer playback
-        if( stream->pDirectSoundOutputBuffer != NULL )
-        {
-            stream->outputIsRunning = FALSE;
-            // FIXME: what happens if IDirectSoundBuffer_Stop returns an error?
-            hr = IDirectSoundBuffer_Stop( stream->pDirectSoundOutputBuffer );
-        }
-    }
-
-    if( stream->bufferProcessor.inputChannelCount > 0 )
-    {
-        // Stop the buffer capture
-        if( stream->pDirectSoundInputBuffer != NULL )
-        {
-            // FIXME: what happens if IDirectSoundCaptureBuffer_Stop returns an error?
-            hr = IDirectSoundCaptureBuffer_Stop( stream->pDirectSoundInputBuffer );
-        }
-    }
-
-    stream->isStarted = FALSE;
-
-    return result;
-}
-
-
-/***********************************************************************************/
-static PaError AbortStream( PaStream *s )
-{
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    stream->abortProcessing = 1;
-    return StopStream( s );
-}
-
-
-/***********************************************************************************/
-static PaError IsStreamStopped( PaStream *s )
-{
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    return !stream->isStarted;
-}
-
-
-/***********************************************************************************/
-static PaError IsStreamActive( PaStream *s )
-{
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    return stream->isActive;
-}
-
-/***********************************************************************************/
-static PaTime GetStreamTime( PaStream *s )
-{
-    /* suppress unused variable warnings */
-    (void) s;
-
-    return PaUtil_GetTime();
-}
-
-
-/***********************************************************************************/
-static double GetStreamCpuLoad( PaStream* s )
-{
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
-}
-
-
-/***********************************************************************************
-    As separate stream interfaces are used for blocking and callback
-    streams, the following functions can be guaranteed to only be called
-    for blocking streams.
-*/
-
-static PaError ReadStream( PaStream* s,
-                           void *buffer,
-                           unsigned long frames )
-{
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) buffer;
-    (void) frames;
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-    return paNoError;
-}
-
-
-/***********************************************************************************/
-static PaError WriteStream( PaStream* s,
-                            const void *buffer,
-                            unsigned long frames )
-{
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) buffer;
-    (void) frames;
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-    return paNoError;
-}
-
-
-/***********************************************************************************/
-static signed long GetStreamReadAvailable( PaStream* s )
-{
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-    return 0;
-}
-
-
-/***********************************************************************************/
-static signed long GetStreamWriteAvailable( PaStream* s )
-{
-    PaWinDsStream *stream = (PaWinDsStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) stream;
-    
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-    return 0;
-}
-
-
-
diff --git a/portaudio/unused/hostapi/dsound/pa_win_ds_dynlink.c b/portaudio/unused/hostapi/dsound/pa_win_ds_dynlink.c
deleted file mode 100644
index 5dca075cd68c9ae1b84b543b2b808154ea97c8d8..0000000000000000000000000000000000000000
--- a/portaudio/unused/hostapi/dsound/pa_win_ds_dynlink.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Interface for dynamically loading directsound and providing a dummy
- * implementation if it isn't present.
- *
- * Author: Ross Bencina (some portions Phil Burk & Robert Marsanyi)
- *
- * For PortAudio Portable Real-Time Audio Library
- * For more information see: http://www.portaudio.com
- * Copyright (c) 1999-2006 Phil Burk, Robert Marsanyi and 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.
- */
-
-/**
- @file
- @ingroup hostaip_src
-*/
-
-#include "pa_win_ds_dynlink.h"
-
-PaWinDsDSoundEntryPoints paWinDsDSoundEntryPoints = { 0, 0, 0, 0, 0, 0, 0 };
-
-
-static HRESULT WINAPI DummyDirectSoundCreate(LPGUID lpcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter)
-{
-    (void)lpcGuidDevice; /* unused parameter */
-    (void)ppDS; /* unused parameter */
-    (void)pUnkOuter; /* unused parameter */
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI DummyDirectSoundEnumerateW(LPDSENUMCALLBACKW lpDSEnumCallback, LPVOID lpContext)
-{
-    (void)lpDSEnumCallback; /* unused parameter */
-    (void)lpContext; /* unused parameter */
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI DummyDirectSoundEnumerateA(LPDSENUMCALLBACKA lpDSEnumCallback, LPVOID lpContext)
-{
-    (void)lpDSEnumCallback; /* unused parameter */
-    (void)lpContext; /* unused parameter */
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI DummyDirectSoundCaptureCreate(LPGUID lpcGUID, LPDIRECTSOUNDCAPTURE *lplpDSC, LPUNKNOWN pUnkOuter)
-{
-    (void)lpcGUID; /* unused parameter */
-    (void)lplpDSC; /* unused parameter */
-    (void)pUnkOuter; /* unused parameter */
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI DummyDirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW lpDSCEnumCallback, LPVOID lpContext)
-{
-    (void)lpDSCEnumCallback; /* unused parameter */
-    (void)lpContext; /* unused parameter */
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI DummyDirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA lpDSCEnumCallback, LPVOID lpContext)
-{
-    (void)lpDSCEnumCallback; /* unused parameter */
-    (void)lpContext; /* unused parameter */
-    return E_NOTIMPL;
-}
-
-
-void PaWinDs_InitializeDSoundEntryPoints(void)
-{
-    paWinDsDSoundEntryPoints.hInstance_ = LoadLibrary("dsound.dll");
-    if( paWinDsDSoundEntryPoints.hInstance_ != NULL )
-    {
-        paWinDsDSoundEntryPoints.DirectSoundCreate =
-                (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN))
-                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCreate" );
-        if( paWinDsDSoundEntryPoints.DirectSoundCreate == NULL )
-            paWinDsDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;
-
-        paWinDsDSoundEntryPoints.DirectSoundEnumerateW =
-                (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
-                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundEnumerateW" );
-        if( paWinDsDSoundEntryPoints.DirectSoundEnumerateW == NULL )
-            paWinDsDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;
-
-        paWinDsDSoundEntryPoints.DirectSoundEnumerateA =
-                (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
-                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundEnumerateA" );
-        if( paWinDsDSoundEntryPoints.DirectSoundEnumerateA == NULL )
-            paWinDsDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;
-
-        paWinDsDSoundEntryPoints.DirectSoundCaptureCreate =
-                (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN))
-                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureCreate" );
-        if( paWinDsDSoundEntryPoints.DirectSoundCaptureCreate == NULL )
-            paWinDsDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;
-
-        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW =
-                (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
-                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateW" );
-        if( paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW == NULL )
-            paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;
-
-        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA =
-                (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
-                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateA" );
-        if( paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA == NULL )
-            paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
-    }
-    else
-    {
-        /* initialize with dummy entry points to make live easy when ds isn't present */
-        paWinDsDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;
-        paWinDsDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;
-        paWinDsDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;
-        paWinDsDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;
-        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;
-        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
-    }
-}
-
-
-void PaWinDs_TerminateDSoundEntryPoints(void)
-{
-    if( paWinDsDSoundEntryPoints.hInstance_ != NULL )
-    {
-        /* ensure that we crash reliably if the entry points arent initialised */
-        paWinDsDSoundEntryPoints.DirectSoundCreate = 0;
-        paWinDsDSoundEntryPoints.DirectSoundEnumerateW = 0;
-        paWinDsDSoundEntryPoints.DirectSoundEnumerateA = 0;
-        paWinDsDSoundEntryPoints.DirectSoundCaptureCreate = 0;
-        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW = 0;
-        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA = 0;
-
-        FreeLibrary( paWinDsDSoundEntryPoints.hInstance_ );
-        paWinDsDSoundEntryPoints.hInstance_ = NULL;
-    }
-}
\ No newline at end of file
diff --git a/portaudio/unused/hostapi/dsound/pa_win_ds_dynlink.h b/portaudio/unused/hostapi/dsound/pa_win_ds_dynlink.h
deleted file mode 100644
index 00e42ea0823829e2fb9e159b60cfa6c3ecab1dca..0000000000000000000000000000000000000000
--- a/portaudio/unused/hostapi/dsound/pa_win_ds_dynlink.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Interface for dynamically loading directsound and providing a dummy
- * implementation if it isn't present.
- *
- * Author: Ross Bencina (some portions Phil Burk & Robert Marsanyi)
- *
- * For PortAudio Portable Real-Time Audio Library
- * For more information see: http://www.portaudio.com
- * Copyright (c) 1999-2006 Phil Burk, Robert Marsanyi and 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.
- */
-
-/**
- @file
- @ingroup hostaip_src
-*/
-
-#ifndef INCLUDED_PA_DSOUND_DYNLINK_H
-#define INCLUDED_PA_DSOUND_DYNLINK_H
-
-/* on Borland compilers, WIN32 doesn't seem to be defined by default, which
-    breaks DSound.h. Adding the define here fixes the problem. - rossb. */
-#ifdef __BORLANDC__
-#if !defined(WIN32)
-#define WIN32
-#endif
-#endif
-
-/*
-  We are only using DX3 in here, no need to polute the namespace - davidv
-*/
-#define DIRECTSOUND_VERSION 0x0300
-
-#include <DSound.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-
-typedef struct
-{
-    HINSTANCE hInstance_;
-    
-    HRESULT (WINAPI *DirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
-    HRESULT (WINAPI *DirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
-    HRESULT (WINAPI *DirectSoundEnumerateA)(LPDSENUMCALLBACKA, LPVOID);
-
-    HRESULT (WINAPI *DirectSoundCaptureCreate)(LPGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN);
-    HRESULT (WINAPI *DirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
-    HRESULT (WINAPI *DirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA, LPVOID);
-}PaWinDsDSoundEntryPoints;
-
-extern PaWinDsDSoundEntryPoints paWinDsDSoundEntryPoints;
-
-void PaWinDs_InitializeDSoundEntryPoints(void);
-void PaWinDs_TerminateDSoundEntryPoints(void);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* INCLUDED_PA_DSOUND_DYNLINK_H */
diff --git a/portaudio/unused/hostapi/wasapi/pa_win_wasapi.cpp b/portaudio/unused/hostapi/wasapi/pa_win_wasapi.cpp
deleted file mode 100644
index 7051496d45dbf10789d888040e05864e6b6d2cc6..0000000000000000000000000000000000000000
--- a/portaudio/unused/hostapi/wasapi/pa_win_wasapi.cpp
+++ /dev/null
@@ -1,1914 +0,0 @@
-/*
- * Portable Audio I/O Library WASAPI implementation
- * Copyright (c) 2006-2007 David Viens
- *
- * Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
- *
- * 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
- @ingroup hostaip_src
- @brief WASAPI implementation of support for a host API.
-
- @note pa_wasapi currently requires VC 2005, and the latest Vista SDK
-*/
-
-#if _MSC_VER >= 1400
-#include <windows.h>
-#include <MMReg.h>  //must be before other Wasapi headers
-#include <strsafe.h>
-#include <mmdeviceapi.h>
-#include <Avrt.h>
-#include <audioclient.h>
-#include <Endpointvolume.h>
-
-#include <KsMedia.h>
-#include <functiondiscoverykeys.h>  // PKEY_Device_FriendlyName
-#endif
-
-#include "pa_util.h"
-#include "pa_allocation.h"
-#include "pa_hostapi.h"
-#include "pa_stream.h"
-#include "pa_cpuload.h"
-#include "pa_process.h"
-#include "pa_debugprint.h"
-
-
-/*
-  davidv : work in progress. try using with 48000 , then 44100
-  and shared mode FIRST.
- */
-
-#define PORTAUDIO_SHAREMODE     AUDCLNT_SHAREMODE_SHARED
-//#define PORTAUDIO_SHAREMODE   AUDCLNT_SHAREMODE_EXCLUSIVE
-
-
-
-/* prototypes for functions declared in this file */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-PaError PaWinWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-
-
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
-static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
-                                  const PaStreamParameters *inputParameters,
-                                  const PaStreamParameters *outputParameters,
-                                  double sampleRate );
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
-                           PaStream** s,
-                           const PaStreamParameters *inputParameters,
-                           const PaStreamParameters *outputParameters,
-                           double sampleRate,
-                           unsigned long framesPerBuffer,
-                           PaStreamFlags streamFlags,
-                           PaStreamCallback *streamCallback,
-                           void *userData );
-static PaError CloseStream( PaStream* stream );
-static PaError StartStream( PaStream *stream );
-static PaError StopStream( PaStream *stream );
-static PaError AbortStream( PaStream *stream );
-static PaError IsStreamStopped( PaStream *s );
-static PaError IsStreamActive( PaStream *stream );
-static PaTime GetStreamTime( PaStream *stream );
-static double GetStreamCpuLoad( PaStream* stream );
-static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
-static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
-static signed long GetStreamReadAvailable( PaStream* stream );
-static signed long GetStreamWriteAvailable( PaStream* stream );
-
-
-/* IMPLEMENT ME: a macro like the following one should be used for reporting
- host errors */
-#define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \
-    PaUtil_SetLastHostErrorInfo( paInDevelopment, errorCode, errorText )
-
-/* PaWinWasapiHostApiRepresentation - host api datastructure specific to this implementation */
-
-
-
-//dummy entry point for other compilers and sdks
-//currently built using RC1 SDK (5600)
-#if _MSC_VER < 1400
-
-PaError PaWinWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ){
-    return paNoError;
-}
-
-#else
-
-
-
-
-#define MAX_STR_LEN 512
-
-/*
- These are fields that can be gathered from IDevice
- and IAudioDevice PRIOR to Initialize, and done in first pass
- i assume that neither of these will cause the Driver to "load",
- but again, who knows how they implement their stuff
- */
-typedef struct PaWinWasapiDeviceInfo
-{
-    //hmm is it wise to keep a reference until Terminate?
-    //TODO Check if that interface requires the driver to be loaded!
-    IMMDevice * device;
-
-    //Fields filled from IDevice
-    //from GetId
-    WCHAR szDeviceID[MAX_STR_LEN];
-    //from GetState
-    DWORD state;
-
-    //Fields filled from IMMEndpoint'sGetDataFlow
-    EDataFlow  flow;
-
-    //Fields filled from IAudioDevice (_prior_ to Initialize)
-    //from GetDevicePeriod(
-    REFERENCE_TIME  DefaultDevicePeriod;
-    REFERENCE_TIME  MinimumDevicePeriod;
-    //from GetMixFormat
-    WAVEFORMATEX   *MixFormat;//needs to be CoTaskMemFree'd after use!
-
-} PaWinWasapiDeviceInfo;
-
-
-typedef struct
-{
-    PaUtilHostApiRepresentation inheritedHostApiRep;
-    PaUtilStreamInterface callbackStreamInterface;
-    PaUtilStreamInterface blockingStreamInterface;
-
-    PaUtilAllocationGroup *allocations;
-
-    /* implementation specific data goes here */
-
-    //in case we later need the synch
-    IMMDeviceEnumerator * enumerator;
-
-    //this is the REAL number of devices, whether they are usefull to PA or not!
-    UINT deviceCount;
-
-    WCHAR defaultRenderer [MAX_STR_LEN];
-    WCHAR defaultCapturer [MAX_STR_LEN];
-
-    PaWinWasapiDeviceInfo   *devInfo;
-}PaWinWasapiHostApiRepresentation;
-
-
-/* PaWinWasapiStream - a stream data structure specifically for this implementation */
-
-typedef struct PaWinWasapiSubStream{
-    IAudioClient        *client;
-    WAVEFORMATEXTENSIBLE wavex;
-    UINT32               bufferSize;
-    REFERENCE_TIME       latency;
-    REFERENCE_TIME       period;
-    unsigned long framesPerHostCallback; /* just an example */
-}PaWinWasapiSubStream;
-
-typedef struct PaWinWasapiStream
-{ /* IMPLEMENT ME: rename this */
-    PaUtilStreamRepresentation streamRepresentation;
-    PaUtilCpuLoadMeasurer cpuLoadMeasurer;
-    PaUtilBufferProcessor bufferProcessor;
-
-    /* IMPLEMENT ME:
-            - implementation specific data goes here
-    */
-
-
-    //input
-	PaWinWasapiSubStream in;
-    IAudioCaptureClient *cclient;
-    IAudioEndpointVolume *inVol;
-	//output
-	PaWinWasapiSubStream out;
-    IAudioRenderClient  *rclient;
-	IAudioEndpointVolume *outVol;
-
-    bool running;
-    bool closeRequest;
-
-    DWORD dwThreadId;
-    HANDLE hThread;
-	HANDLE hNotificationEvent; 
-
-    GUID  session;
-
-}PaWinWasapiStream;
-
-#define PRINT(x) PA_DEBUG(x);
-
-void
-logAUDCLNT_E(HRESULT res){
-
-    char *text = 0;
-    switch(res){
-        case S_OK: return; break;
-        case E_POINTER                              :text ="E_POINTER"; break;
-        case E_INVALIDARG                           :text ="E_INVALIDARG"; break;
-
-        case AUDCLNT_E_NOT_INITIALIZED              :text ="AUDCLNT_E_NOT_INITIALIZED"; break;
-        case AUDCLNT_E_ALREADY_INITIALIZED          :text ="AUDCLNT_E_ALREADY_INITIALIZED"; break;
-        case AUDCLNT_E_WRONG_ENDPOINT_TYPE          :text ="AUDCLNT_E_WRONG_ENDPOINT_TYPE"; break;
-        case AUDCLNT_E_DEVICE_INVALIDATED           :text ="AUDCLNT_E_DEVICE_INVALIDATED"; break;
-        case AUDCLNT_E_NOT_STOPPED                  :text ="AUDCLNT_E_NOT_STOPPED"; break;
-        case AUDCLNT_E_BUFFER_TOO_LARGE             :text ="AUDCLNT_E_BUFFER_TOO_LARGE"; break;
-        case AUDCLNT_E_OUT_OF_ORDER                 :text ="AUDCLNT_E_OUT_OF_ORDER"; break;
-        case AUDCLNT_E_UNSUPPORTED_FORMAT           :text ="AUDCLNT_E_UNSUPPORTED_FORMAT"; break;
-        case AUDCLNT_E_INVALID_SIZE                 :text ="AUDCLNT_E_INVALID_SIZE"; break;
-        case AUDCLNT_E_DEVICE_IN_USE                :text ="AUDCLNT_E_DEVICE_IN_USE"; break;
-        case AUDCLNT_E_BUFFER_OPERATION_PENDING     :text ="AUDCLNT_E_BUFFER_OPERATION_PENDING"; break;
-        case AUDCLNT_E_THREAD_NOT_REGISTERED        :text ="AUDCLNT_E_THREAD_NOT_REGISTERED"; break;      
-		case AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED   :text ="AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED"; break;
-        case AUDCLNT_E_ENDPOINT_CREATE_FAILED       :text ="AUDCLNT_E_ENDPOINT_CREATE_FAILED"; break;
-        case AUDCLNT_E_SERVICE_NOT_RUNNING          :text ="AUDCLNT_E_SERVICE_NOT_RUNNING"; break;
-     //  case AUDCLNT_E_CPUUSAGE_EXCEEDED            :text ="AUDCLNT_E_CPUUSAGE_EXCEEDED"; break;
-     //Header error?
-        case AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED     :text ="AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED"; break;
-        case AUDCLNT_E_EXCLUSIVE_MODE_ONLY          :text ="AUDCLNT_E_EXCLUSIVE_MODE_ONLY"; break;
-        case AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL :text ="AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL"; break;
-        case AUDCLNT_E_EVENTHANDLE_NOT_SET          :text ="AUDCLNT_E_EVENTHANDLE_NOT_SET"; break;
-        case AUDCLNT_E_INCORRECT_BUFFER_SIZE        :text ="AUDCLNT_E_INCORRECT_BUFFER_SIZE"; break;
-        case AUDCLNT_E_BUFFER_SIZE_ERROR            :text ="AUDCLNT_E_BUFFER_SIZE_ERROR"; break;
-        case AUDCLNT_S_BUFFER_EMPTY                 :text ="AUDCLNT_S_BUFFER_EMPTY"; break;
-        case AUDCLNT_S_THREAD_ALREADY_REGISTERED    :text ="AUDCLNT_S_THREAD_ALREADY_REGISTERED"; break;
-        default:
-            text =" dunno!";
-            return ;
-        break;
-
-    }
-    PRINT(("WASAPI ERROR HRESULT: 0x%X : %s\n",res,text));
-}
-
-inline double
-nano100ToMillis(const REFERENCE_TIME &ref){
-    //  1 nano = 0.000000001 seconds
-    //100 nano = 0.0000001   seconds
-    //100 nano = 0.0001   milliseconds
-    return ((double)ref)*0.0001;
-}
-
-inline double
-nano100ToSeconds(const REFERENCE_TIME &ref){
-    //  1 nano = 0.000000001 seconds
-    //100 nano = 0.0000001   seconds
-    //100 nano = 0.0001   milliseconds
-    return ((double)ref)*0.0000001;
-}
-
-#ifndef IF_FAILED_JUMP
-#define IF_FAILED_JUMP(hr, label) if(FAILED(hr)) goto label;
-#endif
-
-
-
-//AVRT is the new "multimedia schedulling stuff"
-
-typedef BOOL   (WINAPI *FAvRtCreateThreadOrderingGroup) (PHANDLE,PLARGE_INTEGER,GUID*,PLARGE_INTEGER);
-typedef BOOL   (WINAPI *FAvRtDeleteThreadOrderingGroup) (HANDLE);
-typedef BOOL   (WINAPI *FAvRtWaitOnThreadOrderingGroup) (HANDLE);
-typedef HANDLE (WINAPI *FAvSetMmThreadCharacteristics)  (LPCTSTR,LPDWORD);
-typedef BOOL   (WINAPI *FAvSetMmThreadPriority)         (HANDLE,AVRT_PRIORITY);
-
-HMODULE  hDInputDLL = 0;
-FAvRtCreateThreadOrderingGroup pAvRtCreateThreadOrderingGroup=0;
-FAvRtDeleteThreadOrderingGroup pAvRtDeleteThreadOrderingGroup=0;
-FAvRtWaitOnThreadOrderingGroup pAvRtWaitOnThreadOrderingGroup=0;
-FAvSetMmThreadCharacteristics  pAvSetMmThreadCharacteristics=0;
-FAvSetMmThreadPriority         pAvSetMmThreadPriority=0;
-
-
-
-#define setupPTR(fun, type, name)  {                                                        \
-                                        fun = (type) GetProcAddress(hDInputDLL,name);       \
-                                        if(fun == NULL) {                                   \
-                                            PRINT(("GetProcAddr failed for %s" ,name));     \
-                                            return false;                                   \
-                                        }                                                   \
-                                    }                                                       \
-
-bool
-setupAVRT(){
-
-    hDInputDLL = LoadLibraryA("avrt.dll");
-    if(hDInputDLL == NULL)
-        return false;
-
-    setupPTR(pAvRtCreateThreadOrderingGroup, FAvRtCreateThreadOrderingGroup, "AvRtCreateThreadOrderingGroup");
-    setupPTR(pAvRtDeleteThreadOrderingGroup, FAvRtDeleteThreadOrderingGroup, "AvRtDeleteThreadOrderingGroup");
-    setupPTR(pAvRtWaitOnThreadOrderingGroup, FAvRtWaitOnThreadOrderingGroup, "AvRtWaitOnThreadOrderingGroup");
-    setupPTR(pAvSetMmThreadCharacteristics,  FAvSetMmThreadCharacteristics,  "AvSetMmThreadCharacteristicsA");
-    setupPTR(pAvSetMmThreadPriority,         FAvSetMmThreadPriority,         "AvSetMmThreadPriority");
-
-    return true;
-}
-
-
-
-PaError PaWinWasapi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
-{
-    if (!setupAVRT()){
-        PRINT(("Windows WASAPI : No AVRT! (not VISTA?)"));
-        return paNoError;
-    }
-
-    CoInitialize(NULL);
-
-    PaError result = paNoError;
-    PaWinWasapiHostApiRepresentation *paWasapi;
-    PaDeviceInfo *deviceInfoArray;
-
-    paWasapi = (PaWinWasapiHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinWasapiHostApiRepresentation) );
-    if( !paWasapi ){
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    paWasapi->allocations = PaUtil_CreateAllocationGroup();
-    if( !paWasapi->allocations ){
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    *hostApi = &paWasapi->inheritedHostApiRep;
-    (*hostApi)->info.structVersion = 1;
-    (*hostApi)->info.type = paWASAPI;
-    (*hostApi)->info.name = "Windows WASAPI";
-    (*hostApi)->info.deviceCount = 0;   //so far, we must investigate each
-    (*hostApi)->info.defaultInputDevice  = paNoDevice;  /* IMPLEMENT ME */
-    (*hostApi)->info.defaultOutputDevice = paNoDevice; /* IMPLEMENT ME */
-
-
-    HRESULT hResult = S_OK;
-    IMMDeviceCollection* spEndpoints=0;
-    paWasapi->enumerator = 0;
-
-    if (!setupAVRT()){
-        PRINT(("Windows WASAPI : No AVRT! (not VISTA?)"));
-        goto error;
-    }
-
-    hResult = CoCreateInstance(
-             __uuidof(MMDeviceEnumerator), NULL,CLSCTX_INPROC_SERVER,
-             __uuidof(IMMDeviceEnumerator),
-             (void**)&paWasapi->enumerator);
-
-    IF_FAILED_JUMP(hResult, error);
-
-    //getting default device ids in the eMultimedia "role"
-    {
-        {
-            IMMDevice* defaultRenderer=0;
-            hResult = paWasapi->enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &defaultRenderer);
-            IF_FAILED_JUMP(hResult, error);
-            WCHAR* pszDeviceId = NULL;
-            hResult = defaultRenderer->GetId(&pszDeviceId);
-            IF_FAILED_JUMP(hResult, error);
-            StringCchCopyW(paWasapi->defaultRenderer, MAX_STR_LEN-1, pszDeviceId);
-            CoTaskMemFree(pszDeviceId);
-            defaultRenderer->Release();
-        }
-
-        {
-            IMMDevice* defaultCapturer=0;
-            hResult = paWasapi->enumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &defaultCapturer);
-            IF_FAILED_JUMP(hResult, error);
-            WCHAR* pszDeviceId = NULL;
-            hResult = defaultCapturer->GetId(&pszDeviceId);
-            IF_FAILED_JUMP(hResult, error);
-            StringCchCopyW(paWasapi->defaultCapturer, MAX_STR_LEN-1, pszDeviceId);
-            CoTaskMemFree(pszDeviceId);
-            defaultCapturer->Release();
-        }
-    }
-
-
-    hResult = paWasapi->enumerator->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE, &spEndpoints);
-    IF_FAILED_JUMP(hResult, error);
-
-    hResult = spEndpoints->GetCount(&paWasapi->deviceCount);
-    IF_FAILED_JUMP(hResult, error);
-
-    paWasapi->devInfo = new PaWinWasapiDeviceInfo[paWasapi->deviceCount];
-    {
-        for (size_t step=0;step<paWasapi->deviceCount;++step)
-            memset(&paWasapi->devInfo[step],0,sizeof(PaWinWasapiDeviceInfo));
-    }
-
-
-
-    if( paWasapi->deviceCount > 0 )
-    {
-        (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
-                paWasapi->allocations, sizeof(PaDeviceInfo*) * paWasapi->deviceCount );
-        if( !(*hostApi)->deviceInfos ){
-            result = paInsufficientMemory;
-            goto error;
-        }
-
-        /* allocate all device info structs in a contiguous block */
-        deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
-                paWasapi->allocations, sizeof(PaDeviceInfo) * paWasapi->deviceCount );
-        if( !deviceInfoArray ){
-            result = paInsufficientMemory;
-            goto error;
-        }
-
-        for( UINT i=0; i < paWasapi->deviceCount; ++i ){
-
-			PA_DEBUG(("i:%d\n",i));
-            PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
-            deviceInfo->structVersion = 2;
-            deviceInfo->hostApi = hostApiIndex;
-
-            hResult = spEndpoints->Item(i, &paWasapi->devInfo[i].device);
-            IF_FAILED_JUMP(hResult, error);
-
-            //getting ID
-            {
-                WCHAR* pszDeviceId = NULL;
-                hResult = paWasapi->devInfo[i].device->GetId(&pszDeviceId);
-                IF_FAILED_JUMP(hResult, error);
-                StringCchCopyW(paWasapi->devInfo[i].szDeviceID, MAX_STR_LEN-1, pszDeviceId);
-                CoTaskMemFree(pszDeviceId);
-
-                if (lstrcmpW(paWasapi->devInfo[i].szDeviceID, paWasapi->defaultCapturer)==0){
-                    //we found the default input!
-                    (*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
-                }
-                if (lstrcmpW(paWasapi->devInfo[i].szDeviceID, paWasapi->defaultRenderer)==0){
-                    //we found the default output!
-                    (*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
-                }
-            }
-
-            DWORD state=0;
-            hResult = paWasapi->devInfo[i].device->GetState(&paWasapi->devInfo[i].state);
-            IF_FAILED_JUMP(hResult, error);
-
-            if (paWasapi->devInfo[i].state != DEVICE_STATE_ACTIVE){
-                PRINT(("WASAPI device:%d is not currently available (state:%d)\n",i,state));
-                //spDevice->Release();
-                //continue;
-            }
-
-            {
-                IPropertyStore* spProperties;
-                hResult = paWasapi->devInfo[i].device->OpenPropertyStore(STGM_READ, &spProperties);
-                IF_FAILED_JUMP(hResult, error);
-
-                //getting "Friendly" Name
-                {
-                    PROPVARIANT value;
-                    PropVariantInit(&value);
-                    hResult = spProperties->GetValue(PKEY_Device_FriendlyName, &value);
-                    IF_FAILED_JUMP(hResult, error);
-                    deviceInfo->name = 0;
-                    char* deviceName = (char*)PaUtil_GroupAllocateMemory( paWasapi->allocations, MAX_STR_LEN + 1 );
-                    if( !deviceName ){
-                        result = paInsufficientMemory;
-                        goto error;
-                    }
-					if (value.pwszVal)
-						wcstombs(deviceName,   value.pwszVal,MAX_STR_LEN-1); //todo proper size	
-					else{
-						sprintf(deviceName,"baddev%d",i);
-					}
-
-                    deviceInfo->name = deviceName;
-                    PropVariantClear(&value);
-                }
-
-#if 0
-                DWORD numProps = 0;
-                hResult = spProperties->GetCount(&numProps);
-                IF_FAILED_JUMP(hResult, error);
-                {
-                    for (DWORD i=0;i<numProps;++i){
-                        PROPERTYKEY pkey;
-                        hResult = spProperties->GetAt(i,&pkey);
-
-                        PROPVARIANT value;
-                        PropVariantInit(&value);
-                        hResult = spProperties->GetValue(pkey, &value);
-
-                        switch(value.vt){
-                            case 11:
-                                PRINT(("property*%u*\n",value.ulVal));
-                            break;
-                            case 19:
-                                PRINT(("property*%d*\n",value.boolVal));
-                            break;
-                            case 31:
-                            {
-                                char temp[512];
-                                wcstombs(temp,    value.pwszVal,MAX_STR_LEN-1);
-                                PRINT(("property*%s*\n",temp));
-                            }
-                            break;
-                            default:break;
-                        }
-
-                        PropVariantClear(&value);
-                    }
-                }
-#endif
-
-                /*  These look interresting... but they are undocumented
-                PKEY_AudioEndpoint_FormFactor
-                PKEY_AudioEndpoint_ControlPanelPageProvider
-                PKEY_AudioEndpoint_Association
-                PKEY_AudioEndpoint_PhysicalSpeakerConfig
-                PKEY_AudioEngine_DeviceFormat
-                */
-                spProperties->Release();
-            }
-
-
-            //getting the Endpoint data
-            {
-                IMMEndpoint *endpoint=0;
-                hResult = paWasapi->devInfo[i].device->QueryInterface(__uuidof(IMMEndpoint),(void **)&endpoint);
-                if (SUCCEEDED(hResult)){
-                    hResult = endpoint->GetDataFlow(&paWasapi->devInfo[i].flow);
-                    endpoint->Release();
-                }
-            }
-
-            //Getting a temporary IAudioDevice for more fields
-            //we make sure NOT to call Initialize yet!
-            {
-                IAudioClient *myClient=0;
-
-                hResult = paWasapi->devInfo[i].device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)&myClient);
-                IF_FAILED_JUMP(hResult, error);
-
-                hResult = myClient->GetDevicePeriod(
-                    &paWasapi->devInfo[i].DefaultDevicePeriod,
-                    &paWasapi->devInfo[i].MinimumDevicePeriod);
-                IF_FAILED_JUMP(hResult, error);
-
-                hResult = myClient->GetMixFormat(&paWasapi->devInfo[i].MixFormat);
-
-				if (hResult != S_OK){
-					/*davidv: this happened with my hardware, previously for that same device in DirectSound:
-					  Digital Output (Realtek AC'97 Audio)'s GUID: {0x38f2cf50,0x7b4c,0x4740,0x86,0xeb,0xd4,0x38,0x66,0xd8,0xc8, 0x9f} 
-					  so something must be _really_ wrong with this device, TODO handle this better. We kind of need GetMixFormat*/
-					logAUDCLNT_E(hResult);
-					goto error;
-				}
-
-                myClient->Release();
-            }
-
-            //we can now fill in portaudio device data
-            deviceInfo->maxInputChannels  = 0;  //for now
-            deviceInfo->maxOutputChannels = 0;  //for now
-
-            switch(paWasapi->devInfo[i].flow){
-                case eRender:
-                    //hum not exaclty maximum, more like "default"
-                    deviceInfo->maxOutputChannels = paWasapi->devInfo[i].MixFormat->nChannels;
-
-                    deviceInfo->defaultHighOutputLatency = nano100ToSeconds(paWasapi->devInfo[i].DefaultDevicePeriod);
-                    deviceInfo->defaultLowOutputLatency  = nano100ToSeconds(paWasapi->devInfo[i].MinimumDevicePeriod);
-                break;
-                case eCapture:
-                    //hum not exaclty maximum, more like "default"
-                    deviceInfo->maxInputChannels  = paWasapi->devInfo[i].MixFormat->nChannels;
-
-                    deviceInfo->defaultHighInputLatency = nano100ToSeconds(paWasapi->devInfo[i].DefaultDevicePeriod);
-                    deviceInfo->defaultLowInputLatency  = nano100ToSeconds(paWasapi->devInfo[i].MinimumDevicePeriod);
-                break;
-                default:
-                    PRINT(("WASAPI device:%d bad Data FLow! \n",i));
-                    goto error;
-                break;
-            }
-
-            deviceInfo->defaultSampleRate = (double)paWasapi->devInfo[i].MixFormat->nSamplesPerSec;
-
-            (*hostApi)->deviceInfos[i] = deviceInfo;
-            ++(*hostApi)->info.deviceCount;
-        }
-    }
-
-    spEndpoints->Release();
-
-    (*hostApi)->Terminate = Terminate;
-    (*hostApi)->OpenStream = OpenStream;
-    (*hostApi)->IsFormatSupported = IsFormatSupported;
-
-    PaUtil_InitializeStreamInterface( &paWasapi->callbackStreamInterface, CloseStream, StartStream,
-                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
-                                      GetStreamTime, GetStreamCpuLoad,
-                                      PaUtil_DummyRead, PaUtil_DummyWrite,
-                                      PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
-
-    PaUtil_InitializeStreamInterface( &paWasapi->blockingStreamInterface, CloseStream, StartStream,
-                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
-                                      GetStreamTime, PaUtil_DummyGetCpuLoad,
-                                      ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
-
-    return result;
-
-error:
-
-    if (spEndpoints)
-        spEndpoints->Release();
-
-    if (paWasapi->enumerator)
-        paWasapi->enumerator->Release();
-
-    if( paWasapi )
-    {
-        if( paWasapi->allocations )
-        {
-            PaUtil_FreeAllAllocations( paWasapi->allocations );
-            PaUtil_DestroyAllocationGroup( paWasapi->allocations );
-        }
-
-        PaUtil_FreeMemory( paWasapi );
-    }
-    return result;
-}
-
-
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
-{
-    PaWinWasapiHostApiRepresentation *paWasapi = (PaWinWasapiHostApiRepresentation*)hostApi;
-
-    paWasapi->enumerator->Release();
-
-    for (UINT i=0;i<paWasapi->deviceCount;++i){
-        PaWinWasapiDeviceInfo *info = &paWasapi->devInfo[i];
-
-        if (info->device)
-            info->device->Release();
-
-        if (info->MixFormat)
-            CoTaskMemFree(info->MixFormat);
-    }
-    delete [] paWasapi->devInfo;
-
-    CoUninitialize();
-
-    if( paWasapi->allocations ){
-        PaUtil_FreeAllAllocations( paWasapi->allocations );
-        PaUtil_DestroyAllocationGroup( paWasapi->allocations );
-    }
-
-    PaUtil_FreeMemory( paWasapi );
-}
-
-static void
-LogWAVEFORMATEXTENSIBLE(const WAVEFORMATEXTENSIBLE *in){
-
-    const WAVEFORMATEX *old = (WAVEFORMATEX *)in;
-
-	switch (old->wFormatTag){
-		case WAVE_FORMAT_EXTENSIBLE:{
-
-			PRINT(("wFormatTag=WAVE_FORMAT_EXTENSIBLE\n"));
-
-			if (in->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT){
-				PRINT(("SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT\n"));
-			}
-			else if (in->SubFormat == KSDATAFORMAT_SUBTYPE_PCM){
-				PRINT(("SubFormat=KSDATAFORMAT_SUBTYPE_PCM\n"));
-			}
-			else{
-				PRINT(("SubFormat=CUSTOM GUID{%d:%d:%d:%d%d%d%d%d%d%d%d}\n",	
-											in->SubFormat.Data1,
-											in->SubFormat.Data2,
-											in->SubFormat.Data3,
-											(int)in->SubFormat.Data4[0],
-											(int)in->SubFormat.Data4[1],
-											(int)in->SubFormat.Data4[2],
-											(int)in->SubFormat.Data4[3],
-											(int)in->SubFormat.Data4[4],
-											(int)in->SubFormat.Data4[5],
-											(int)in->SubFormat.Data4[6],
-											(int)in->SubFormat.Data4[7]));
-			}
-			PRINT(("Samples.wValidBitsPerSample=%d\n",  in->Samples.wValidBitsPerSample));
-			PRINT(("dwChannelMask=0x%X\n",in->dwChannelMask));
-		}break;
-		
-		case WAVE_FORMAT_PCM:        PRINT(("wFormatTag=WAVE_FORMAT_PCM\n")); break;
-		case WAVE_FORMAT_IEEE_FLOAT: PRINT(("wFormatTag=WAVE_FORMAT_IEEE_FLOAT\n")); break;
-		default : PRINT(("wFormatTag=UNKNOWN(%d)\n",old->wFormatTag)); break;
-	}
-
-	PRINT(("nChannels      =%d\n",old->nChannels)); 
-	PRINT(("nSamplesPerSec =%d\n",old->nSamplesPerSec));  
-	PRINT(("nAvgBytesPerSec=%d\n",old->nAvgBytesPerSec));  
-	PRINT(("nBlockAlign    =%d\n",old->nBlockAlign));  
-	PRINT(("wBitsPerSample =%d\n",old->wBitsPerSample));  
-	PRINT(("cbSize         =%d\n",old->cbSize));  
-}
-
-
-
-/*
- WAVEFORMATXXX is always interleaved
- */
-static PaSampleFormat
-waveformatToPaFormat(const WAVEFORMATEXTENSIBLE *in){
-
-    const WAVEFORMATEX *old = (WAVEFORMATEX*)in;
-
-    switch (old->wFormatTag){
-
-        case WAVE_FORMAT_EXTENSIBLE:
-        {
-            if (in->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT){
-                if (in->Samples.wValidBitsPerSample == 32)
-                    return paFloat32;
-                else
-                    return paCustomFormat;
-            }
-            else if (in->SubFormat == KSDATAFORMAT_SUBTYPE_PCM){
-                switch (old->wBitsPerSample){
-                    case 32: return paInt32; break;
-                    case 24: return paInt24;break;
-                    case  8: return paUInt8;break;
-                    case 16: return paInt16;break;
-                    default: return paCustomFormat;break;
-                }
-            }
-            else
-                return paCustomFormat;
-        }
-        break;
-
-        case WAVE_FORMAT_IEEE_FLOAT:
-            return paFloat32;
-        break;
-
-        case WAVE_FORMAT_PCM:
-        {
-            switch (old->wBitsPerSample){
-                case 32: return paInt32; break;
-                case 24: return paInt24;break;
-                case  8: return paUInt8;break;
-                case 16: return paInt16;break;
-                default: return paCustomFormat;break;
-            }
-        }
-        break;
-
-        default:
-            return paCustomFormat;
-        break;
-    }
-
-    return paCustomFormat;
-}
-
-
-
-static PaError
-waveformatFromParams(WAVEFORMATEXTENSIBLE*wavex,
-                          const PaStreamParameters * params,
-                          double sampleRate){
-
-    size_t bytesPerSample = 0;
-    switch( params->sampleFormat & ~paNonInterleaved ){
-        case paFloat32:
-        case paInt32: bytesPerSample=4;break;
-        case paInt16: bytesPerSample=2;break;
-        case paInt24: bytesPerSample=3;break;
-        case paInt8:
-        case paUInt8: bytesPerSample=1;break;
-        case paCustomFormat:
-        default: return paSampleFormatNotSupported;break;
-    }
-
-    memset(wavex,0,sizeof(WAVEFORMATEXTENSIBLE));
-
-    WAVEFORMATEX *old    = (WAVEFORMATEX *)wavex;
-    old->nChannels       = (WORD)params->channelCount;
-    old->nSamplesPerSec  = (DWORD)sampleRate;
-    old->wBitsPerSample  = (WORD)(bytesPerSample*8);
-    old->nAvgBytesPerSec = (DWORD)(old->nSamplesPerSec * old->nChannels * bytesPerSample);
-    old->nBlockAlign     = (WORD)(old->nChannels * bytesPerSample);
-
-    //WAVEFORMATEX
-    if (params->channelCount <=2 && (bytesPerSample == 2 || bytesPerSample == 1)){
-        old->cbSize          = 0;
-        old->wFormatTag      = WAVE_FORMAT_PCM;
-    }
-    //WAVEFORMATEXTENSIBLE
-    else{
-        old->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
-
-        old->cbSize = sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX);
-
-        if ((params->sampleFormat & ~paNonInterleaved) == paFloat32)
-            wavex->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
-        else
-            wavex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-
-        wavex->Samples.wValidBitsPerSample = old->wBitsPerSample; //no extra padding!
-
-        switch(params->channelCount){
-            case 1:  wavex->dwChannelMask = SPEAKER_FRONT_CENTER; break;
-            case 2:  wavex->dwChannelMask = 0x1 | 0x2; break;
-            case 4:  wavex->dwChannelMask = 0x1 | 0x2 | 0x10 | 0x20; break;
-            case 6:  wavex->dwChannelMask = 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20; break;
-            case 8:  wavex->dwChannelMask = 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80; break;
-            default: wavex->dwChannelMask = 0; break;
-        }
-    }
-
-    return paNoError;
-}
-
-
-
-
-
-
-/*
-#define paFloat32        ((PaSampleFormat) 0x00000001) 
-#define paInt32          ((PaSampleFormat) 0x00000002)
-#define paInt24          ((PaSampleFormat) 0x00000004) 
-#define paInt16          ((PaSampleFormat) 0x00000008) 
-*/
-//lifted from pa_wdmks
-static void wasapiFillWFEXT( WAVEFORMATEXTENSIBLE* pwfext, PaSampleFormat sampleFormat, double sampleRate, int channelCount)
-{
-    PA_DEBUG(( "sampleFormat = %lx\n" , sampleFormat ));
-    PA_DEBUG(( "sampleRate = %f\n" , sampleRate ));
-    PA_DEBUG(( "chanelCount = %d\n", channelCount ));
-
-    pwfext->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
-    pwfext->Format.nChannels = channelCount;
-    pwfext->Format.nSamplesPerSec = (int)sampleRate;
-    if(channelCount == 1)
-        pwfext->dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT;
-    else
-        pwfext->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
-    if(sampleFormat == paFloat32)
-    {
-        pwfext->Format.nBlockAlign = channelCount * 4;
-        pwfext->Format.wBitsPerSample = 32;
-        pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
-        pwfext->Samples.wValidBitsPerSample = 32;
-        pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
-    }
-    else if(sampleFormat == paInt32)
-    {
-        pwfext->Format.nBlockAlign = channelCount * 4;
-        pwfext->Format.wBitsPerSample = 32;
-        pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
-        pwfext->Samples.wValidBitsPerSample = 32;
-        pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-    }
-    else if(sampleFormat == paInt24)
-    {
-        pwfext->Format.nBlockAlign = channelCount * 3;
-        pwfext->Format.wBitsPerSample = 24;
-        pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
-        pwfext->Samples.wValidBitsPerSample = 24;
-        pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-    }
-    else if(sampleFormat == paInt16)
-    {
-        pwfext->Format.nBlockAlign = channelCount * 2;
-        pwfext->Format.wBitsPerSample = 16;
-        pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
-        pwfext->Samples.wValidBitsPerSample = 16;
-        pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-    }
-    pwfext->Format.nAvgBytesPerSec = pwfext->Format.nSamplesPerSec * pwfext->Format.nBlockAlign;
-}
-
-
-
-/*
-#define FORMATTESTS 4
-const int BestToWorst[FORMATTESTS]={paFloat32,paInt32,paInt24,paInt16};
-*/
-
-#define FORMATTESTS 3
-const int BestToWorst[FORMATTESTS]={paFloat32,paInt24,paInt16};
-
-
-static PaError
-GetClosestFormat(IAudioClient * myClient, double sampleRate,const  PaStreamParameters * params, 
-				 AUDCLNT_SHAREMODE *shareMode, WAVEFORMATEXTENSIBLE *outWavex)
-{
-	//TODO we should try exclusive first and shared after
-	*shareMode = PORTAUDIO_SHAREMODE;
-
-	PaError answer = paInvalidSampleRate;
-
-    waveformatFromParams(outWavex,params,sampleRate);
-	WAVEFORMATEX *sharedClosestMatch=0;
-	HRESULT hResult=!S_OK;
-
-	if (*shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)
-		hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,(WAVEFORMATEX*)outWavex,NULL);
-	else
-		hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,   (WAVEFORMATEX*)&outWavex,&sharedClosestMatch);
-
-	if (hResult == S_OK)
-		answer = paFormatIsSupported;
-    else if (sharedClosestMatch){
-        WAVEFORMATEXTENSIBLE* ext = (WAVEFORMATEXTENSIBLE*)sharedClosestMatch;
-		
-		int closestMatchSR = (int)sharedClosestMatch->nSamplesPerSec;
-
-		if (sharedClosestMatch->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
-			memcpy(outWavex,sharedClosestMatch,sizeof(WAVEFORMATEXTENSIBLE));
-		else
-			memcpy(outWavex,sharedClosestMatch,sizeof(WAVEFORMATEX));
-
-        CoTaskMemFree(sharedClosestMatch);
-
-		if ((int)sampleRate == closestMatchSR)
-		answer = paFormatIsSupported;
-		else
-			answer = paInvalidSampleRate;
-	
-	}else {
-
-		//it doesnt suggest anything?? ok lets show it the MENU!
-
-		//ok fun time as with pa_win_mme, we know only a refusal of the user-requested
-		//sampleRate+num Channel is disastrous, as the portaudio buffer processor converts between anything
-		//so lets only use the number 
-		for (int i=0;i<FORMATTESTS;++i){
-			WAVEFORMATEXTENSIBLE ext;
-			wasapiFillWFEXT(&ext,BestToWorst[i],sampleRate,params->channelCount);		
-			if (*shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)
-				hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,(WAVEFORMATEX*)&ext,NULL);
-			else
-				hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,   (WAVEFORMATEX*)&ext,&sharedClosestMatch);
-
-			if (hResult == S_OK){
-				memcpy(outWavex,&ext,sizeof(WAVEFORMATEXTENSIBLE));
-				answer = paFormatIsSupported;
-				break;
-			}
-		}
-
-		if (answer!=paFormatIsSupported) {
-			//try MIX format?
-			//why did it HAVE to come to this ....
-			WAVEFORMATEX pcm16WaveFormat;
-			memset(&pcm16WaveFormat,0,sizeof(WAVEFORMATEX));
-			pcm16WaveFormat.wFormatTag = WAVE_FORMAT_PCM; 
-			pcm16WaveFormat.nChannels = 2; 
-			pcm16WaveFormat.nSamplesPerSec = (DWORD)sampleRate; 
-			pcm16WaveFormat.nBlockAlign = 4; 
-			pcm16WaveFormat.nAvgBytesPerSec = pcm16WaveFormat.nSamplesPerSec*pcm16WaveFormat.nBlockAlign; 
-			pcm16WaveFormat.wBitsPerSample = 16; 
-			pcm16WaveFormat.cbSize = 0;
-
-			if (*shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)
-				hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,(WAVEFORMATEX*)&pcm16WaveFormat,NULL);
-			else
-				hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,   (WAVEFORMATEX*)&pcm16WaveFormat,&sharedClosestMatch);
-
-			if (hResult == S_OK){
-				memcpy(outWavex,&pcm16WaveFormat,sizeof(WAVEFORMATEX));
-				answer = paFormatIsSupported;
-			}
-		}
-
-		logAUDCLNT_E(hResult);
-	}
-
-	return answer;
-}
-
-
-static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
-                                  const  PaStreamParameters *inputParameters,
-                                  const  PaStreamParameters *outputParameters,
-                                  double sampleRate )
-{
-
-    int inputChannelCount, outputChannelCount;
-    PaSampleFormat inputSampleFormat, outputSampleFormat;
-
-    if( inputParameters )
-    {
-        inputChannelCount = inputParameters->channelCount;
-        inputSampleFormat = inputParameters->sampleFormat;
-
-        /* all standard sample formats are supported by the buffer adapter,
-            this implementation doesn't support any custom sample formats */
-        if( inputSampleFormat & paCustomFormat )
-            return paSampleFormatNotSupported;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that input device can support inputChannelCount */
-        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
-            return paInvalidChannelCount;
-
-        /* validate inputStreamInfo */
-        if( inputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-
-
-        PaWinWasapiHostApiRepresentation *paWasapi = (PaWinWasapiHostApiRepresentation*)hostApi;
-
-
-		IAudioClient *myClient=0;
-		HRESULT hResult = paWasapi->devInfo[inputParameters->device].device->Activate(
-			__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)&myClient);
-		if (hResult != S_OK){
-			logAUDCLNT_E(hResult);
-			return paInvalidDevice;
-		}
-
-        WAVEFORMATEXTENSIBLE wavex;
-		AUDCLNT_SHAREMODE shareMode;
-		PaError answer = GetClosestFormat(myClient,sampleRate,inputParameters,&shareMode,&wavex);
-		myClient->Release();
-
-		if (answer !=paFormatIsSupported)
-			return answer;
-    }
-    else
-    {
-        inputChannelCount = 0;
-    }
-
-    if( outputParameters )
-    {
-        outputChannelCount = outputParameters->channelCount;
-        outputSampleFormat = outputParameters->sampleFormat;
-
-        /* all standard sample formats are supported by the buffer adapter,
-            this implementation doesn't support any custom sample formats */
-        if( outputSampleFormat & paCustomFormat )
-            return paSampleFormatNotSupported;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that output device can support outputChannelCount */
-        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
-            return paInvalidChannelCount;
-
-        /* validate outputStreamInfo */
-        if( outputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-
-
-        PaWinWasapiHostApiRepresentation *paWasapi = (PaWinWasapiHostApiRepresentation*)hostApi;
-
-		IAudioClient *myClient=0;
-		HRESULT hResult = paWasapi->devInfo[outputParameters->device].device->Activate(
-			__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)&myClient);
-		if (hResult != S_OK){
-			logAUDCLNT_E(hResult);
-			return paInvalidDevice;
-		}
-
-        WAVEFORMATEXTENSIBLE wavex;
-		AUDCLNT_SHAREMODE shareMode;
-		PaError answer = GetClosestFormat(myClient,sampleRate,outputParameters,&shareMode,&wavex);
-		myClient->Release();
-
-		if (answer !=paFormatIsSupported)
-			return answer;		
-    }
-    else
-    {
-        outputChannelCount = 0;
-    }
-
-
-    return paFormatIsSupported;
-}
-
-
-
-/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
-
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
-                           PaStream** s,
-                           const PaStreamParameters *inputParameters,
-                           const PaStreamParameters *outputParameters,
-                           double sampleRate,
-                           unsigned long framesPerBuffer,
-                           PaStreamFlags streamFlags,
-                           PaStreamCallback *streamCallback,
-                           void *userData )
-{
-    PaError result = paNoError;
-    PaWinWasapiHostApiRepresentation *paWasapi = (PaWinWasapiHostApiRepresentation*)hostApi;
-    PaWinWasapiStream *stream = 0;
-    int inputChannelCount, outputChannelCount;
-    PaSampleFormat inputSampleFormat, outputSampleFormat;
-    PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
-
-
-    stream = (PaWinWasapiStream*)PaUtil_AllocateMemory( sizeof(PaWinWasapiStream) );
-    if( !stream ){
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    if( inputParameters )
-    {
-        inputChannelCount = inputParameters->channelCount;
-        inputSampleFormat = inputParameters->sampleFormat;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that input device can support inputChannelCount */
-        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
-            return paInvalidChannelCount;
-
-        /* validate inputStreamInfo */
-        if( inputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-
-
-        PaWinWasapiDeviceInfo &info = paWasapi->devInfo[inputParameters->device];
-
-        HRESULT hResult = info.device->Activate(
-            __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL,
-            (void**)&stream->in.client);
-
-        if (hResult != S_OK)
-            return paInvalidDevice;
-
-        hResult = info.device->Activate(
-            __uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL,
-            (void**)&stream->inVol);
-
-        if (hResult != S_OK)
-            return paInvalidDevice;
-	
-		AUDCLNT_SHAREMODE shareMode;
-		PaError answer = GetClosestFormat(stream->in.client,sampleRate,inputParameters,&shareMode,&stream->in.wavex);
-		
-		if (answer !=paFormatIsSupported)
-			return answer;
-
-        //stream->out.period = info.DefaultDevicePeriod;
-        stream->in.period = info.MinimumDevicePeriod;
-
-        hResult = stream->in.client->Initialize(
-            shareMode,
-            0,  //no flags
-            stream->in.period,
-            0,//stream->out.period,
-            (WAVEFORMATEX*)&stream->in.wavex,
-            &stream->session
-            );
-
-        if (hResult != S_OK){
-            logAUDCLNT_E(hResult);
-            return paInvalidDevice;
-        }
-
-        hResult = stream->in.client->GetBufferSize(&stream->in.bufferSize);
-        if (hResult != S_OK)
-            return paInvalidDevice;
-
-        hResult = stream->in.client->GetStreamLatency(&stream->in.latency);
-        if (hResult != S_OK)
-            return paInvalidDevice;
-
-        double periodsPerSecond = 1.0/nano100ToSeconds(stream->in.period);
-        double samplesPerPeriod = (double)(stream->in.wavex.Format.nSamplesPerSec)/periodsPerSecond;
-
-        //this is the number of samples that are required at each period
-        stream->in.framesPerHostCallback = (unsigned long)samplesPerPeriod;//unrelated to channels
-
-        /* IMPLEMENT ME - establish which  host formats are available */
-        hostInputSampleFormat =
-            PaUtil_SelectClosestAvailableFormat( waveformatToPaFormat(&stream->in.wavex), inputSampleFormat );
-	}
-    else
-    {
-        inputChannelCount = 0;
-        inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
-    }
-
-    if( outputParameters )
-    {
-        outputChannelCount = outputParameters->channelCount;
-        outputSampleFormat = outputParameters->sampleFormat;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that output device can support inputChannelCount */
-        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
-            return paInvalidChannelCount;
-
-        /* validate outputStreamInfo */
-        if( outputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-
-
-        PaWinWasapiDeviceInfo &info = paWasapi->devInfo[outputParameters->device];
-
-        HRESULT hResult = info.device->Activate(
-            __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL,
-            (void**)&stream->out.client);
-
-        if (hResult != S_OK)
-            return paInvalidDevice;
-
-		AUDCLNT_SHAREMODE shareMode;
-		PaError answer = GetClosestFormat(stream->out.client,sampleRate,outputParameters,&shareMode,&stream->out.wavex);
-		
-		if (answer !=paFormatIsSupported)
-			return answer;
-		LogWAVEFORMATEXTENSIBLE(&stream->out.wavex);
-
-       // stream->out.period = info.DefaultDevicePeriod;
-        stream->out.period = info.MinimumDevicePeriod;
-
-		/*For an exclusive-mode stream that uses event-driven buffering, 
-		the caller must specify nonzero values for hnsPeriodicity and hnsBufferDuration, 
-		and the values of these two parameters must be equal */
-		if (shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE){
-			hResult = stream->out.client->Initialize(
-				shareMode,
-				AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 
-				stream->out.period,
-				stream->out.period,
-				(WAVEFORMATEX*)&stream->out.wavex,
-				&stream->session
-				);
-		}
-		else{
-			hResult = stream->out.client->Initialize(
-				shareMode,
-				AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 
-				0,
-				0,
-				(WAVEFORMATEX*)&stream->out.wavex,
-				&stream->session
-				);
-		}
-	
-
-        if (hResult != S_OK){
-            logAUDCLNT_E(hResult);
-            return paInvalidDevice;
-        }
-
-        hResult = info.device->Activate(
-            __uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL,
-            (void**)&stream->outVol);
-
-        if (hResult != S_OK)
-            return paInvalidDevice;
-
-        hResult = stream->out.client->GetBufferSize(&stream->out.bufferSize);
-        if (hResult != S_OK)
-            return paInvalidDevice;
-
-        hResult = stream->out.client->GetStreamLatency(&stream->out.latency);
-        if (hResult != S_OK)
-            return paInvalidDevice;
-		
-        double periodsPerSecond = 1.0/nano100ToSeconds(stream->out.period);
-        double samplesPerPeriod = (double)(stream->out.wavex.Format.nSamplesPerSec)/periodsPerSecond;
-
-        //this is the number of samples that are required at each period
-        stream->out.framesPerHostCallback = stream->out.bufferSize; //(unsigned long)samplesPerPeriod;//unrelated to channels
-
-        /* IMPLEMENT ME - establish which  host formats are available */
-        hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( waveformatToPaFormat(&stream->out.wavex), outputSampleFormat );
-    }
-    else
-    {
-        outputChannelCount = 0;
-        outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
-    }
-
-
-
-    /*
-        IMPLEMENT ME:
-
-        ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() FIXME - checks needed? )
-
-            - check that input device can support inputSampleFormat, or that
-                we have the capability to convert from outputSampleFormat to
-                a native format
-
-            - check that output device can support outputSampleFormat, or that
-                we have the capability to convert from outputSampleFormat to
-                a native format
-
-            - if a full duplex stream is requested, check that the combination
-                of input and output parameters is supported
-
-            - check that the device supports sampleRate
-
-            - alter sampleRate to a close allowable rate if possible / necessary
-
-            - validate suggestedInputLatency and suggestedOutputLatency parameters,
-                use default values where necessary
-    */
-
-
-
-    /* validate platform specific flags */
-    if( (streamFlags & paPlatformSpecificFlags) != 0 )
-        return paInvalidFlag; /* unexpected platform specific flag */
-
-
-
-    if( streamCallback )
-    {
-        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
-                                               &paWasapi->callbackStreamInterface, streamCallback, userData );
-    }
-    else
-    {
-        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
-                                               &paWasapi->blockingStreamInterface, streamCallback, userData );
-    }
-
-    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
-
-
-	if (outputParameters && inputParameters){
-
-		//serious problem #1
-		if (stream->in.period != stream->out.period){
-			PRINT(("OpenStream: period discrepancy\n"));
-			goto error;
-		}
-
-		//serious problem #2
-		if (stream->out.framesPerHostCallback != stream->in.framesPerHostCallback){
-			PRINT(("OpenStream: framesPerHostCallback discrepancy\n"));
-			goto error;
-		}
-	}
-
-	unsigned long framesPerHostCallback = (outputParameters)?
-		stream->out.framesPerHostCallback: 
-		stream->in.framesPerHostCallback;
-
-    /* we assume a fixed host buffer size in this example, but the buffer processor
-        can also support bounded and unknown host buffer sizes by passing
-        paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of
-        paUtilFixedHostBufferSize below. */
-
-    result =  PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
-              inputChannelCount, inputSampleFormat, hostInputSampleFormat,
-              outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
-              sampleRate, streamFlags, framesPerBuffer,
-              framesPerHostCallback, paUtilFixedHostBufferSize,
-              streamCallback, userData );
-    if( result != paNoError )
-        goto error;
-
-
-    /*
-        IMPLEMENT ME: initialise the following fields with estimated or actual
-        values.
-    */
-    stream->streamRepresentation.streamInfo.inputLatency =
-            PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor)
-			+ ((inputParameters)?nano100ToSeconds(stream->in.latency) :0);
-
-    stream->streamRepresentation.streamInfo.outputLatency =
-            PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor)
-			+ ((outputParameters)?nano100ToSeconds(stream->out.latency) :0);
-
-    stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
-
-
-    *s = (PaStream*)stream;
-
-
-    return result;
-
-error:
-    if( stream )
-        PaUtil_FreeMemory( stream );
-
-    return result;
-}
-
-
-
-/*
-    When CloseStream() is called, the multi-api layer ensures that
-    the stream has already been stopped or aborted.
-*/
-
-#define SAFE_RELEASE(punk)  \
-              if ((punk) != NULL)  \
-                { (punk)->Release(); (punk) = NULL; }
-
-static PaError CloseStream( PaStream* s )
-{
-    PaError result = paNoError;
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    /*
-        IMPLEMENT ME:
-            - additional stream closing + cleanup
-    */
-
-    SAFE_RELEASE(stream->out.client);
-    SAFE_RELEASE(stream->in.client);
-    SAFE_RELEASE(stream->cclient);
-    SAFE_RELEASE(stream->rclient);
-	SAFE_RELEASE(stream->inVol);
-	SAFE_RELEASE(stream->outVol);
-    CloseHandle(stream->hThread);
-	CloseHandle(stream->hNotificationEvent);
-
-    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
-    PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
-    PaUtil_FreeMemory( stream );
-
-    return result;
-}
-
-VOID ProcThread(void *client);
-
-static PaError StartStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
-	
-	HRESULT hResult=S_OK;
-
-	if (stream->out.client){
-		hResult = stream->out.client->GetService(__uuidof(IAudioRenderClient),(void**)&stream->rclient);
-		logAUDCLNT_E(hResult);
-		if (hResult!=S_OK)
-			return paUnanticipatedHostError;
-	}
-	
-	if (stream->in.client){
-	 hResult = stream->in.client->GetService(__uuidof(IAudioCaptureClient),(void**)&stream->cclient);
-		logAUDCLNT_E(hResult);
-		if (hResult!=S_OK)
-			return paUnanticipatedHostError;
-	}
-
-    // Create a thread for this client.
-    stream->hThread = CreateThread(
-        NULL,              // no security attribute
-        0,                 // default stack size
-        (LPTHREAD_START_ROUTINE) ProcThread,
-        (LPVOID) stream,    // thread parameter
-        0,                 // not suspended
-        &stream->dwThreadId);      // returns thread ID
-
-    if (stream->hThread == NULL)
-        return paUnanticipatedHostError;
-
-    return paNoError;
-}
-
-
-static PaError StopStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    /* suppress unused variable warnings */
-    stream->closeRequest = true;
-    //todo something MUCH better than this
-    while(stream->closeRequest)
-        Sleep(100);
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior */
-
-    stream->running = false;
-
-    return result;
-}
-
-
-static PaError AbortStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    /* suppress unused variable warnings */
-    stream->closeRequest = true;
-    //todo something MUCH better than this
-    while(stream->closeRequest)
-        Sleep(100);
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior */
-
-    return result;
-}
-
-
-static PaError IsStreamStopped( PaStream *s )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    return !stream->running;
-}
-
-
-static PaError IsStreamActive( PaStream *s )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-    return stream->running;
-}
-
-
-static PaTime GetStreamTime( PaStream *s )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-	//this is lame ds and mme does the same thing, quite useless method imho
-	//why dont we fetch the time in the pa callbacks?
-	//at least its doing to be clocked to something
-    return PaUtil_GetTime();
-}
-
-
-static double GetStreamCpuLoad( PaStream* s )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
-}
-
-
-/*
-    As separate stream interfaces are used for blocking and callback
-    streams, the following functions can be guaranteed to only be called
-    for blocking streams.
-*/
-
-static PaError ReadStream( PaStream* s,
-                           void *buffer,
-                           unsigned long frames )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) buffer;
-    (void) frames;
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-    return paNoError;
-}
-
-
-static PaError WriteStream( PaStream* s,
-                            const void *buffer,
-                            unsigned long frames )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) buffer;
-    (void) frames;
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-    return paNoError;
-}
-
-
-static signed long GetStreamReadAvailable( PaStream* s )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-    return 0;
-}
-
-
-static signed long GetStreamWriteAvailable( PaStream* s )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)s;
-
-    /* suppress unused variable warnings */
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-
-    return 0;
-}
-
-
-
-/*
-    ExampleHostProcessingLoop() illustrates the kind of processing which may
-    occur in a host implementation.
-
-*/
-static void WaspiHostProcessingLoop( void *inputBuffer,  long inputFrames,
-                                     void *outputBuffer, long outputFrames,
-                                     void *userData )
-{
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)userData;
-    PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
-    int callbackResult;
-    unsigned long framesProcessed;
-
-    PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
-
-
-    /*
-        IMPLEMENT ME:
-            - generate timing information
-            - handle buffer slips
-    */
-
-    /*
-        If you need to byte swap or shift inputBuffer to convert it into a
-        portaudio format, do it here.
-    */
-
-
-
-    PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 /* IMPLEMENT ME: pass underflow/overflow flags when necessary */ );
-
-    /*
-        depending on whether the host buffers are interleaved, non-interleaved
-        or a mixture, you will want to call PaUtil_SetInterleaved*Channels(),
-        PaUtil_SetNonInterleaved*Channel() or PaUtil_Set*Channel() here.
-    */
-
-    if( stream->bufferProcessor.inputChannelCount > 0 )
-    {
-        PaUtil_SetInputFrameCount( &stream->bufferProcessor, inputFrames );
-        PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
-            0, /* first channel of inputBuffer is channel 0 */
-            inputBuffer,
-            0 ); /* 0 - use inputChannelCount passed to init buffer processor */
-    }
-
-    if( stream->bufferProcessor.outputChannelCount > 0 )
-    {
-        PaUtil_SetOutputFrameCount( &stream->bufferProcessor, outputFrames);
-        PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
-            0, /* first channel of outputBuffer is channel 0 */
-            outputBuffer,
-            0 ); /* 0 - use outputChannelCount passed to init buffer processor */
-    }
-
-    /* you must pass a valid value of callback result to PaUtil_EndBufferProcessing()
-        in general you would pass paContinue for normal operation, and
-        paComplete to drain the buffer processor's internal output buffer.
-        You can check whether the buffer processor's output buffer is empty
-        using PaUtil_IsBufferProcessorOuputEmpty( bufferProcessor )
-    */
-    callbackResult = paContinue;
-    framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );
-
-
-    /*
-        If you need to byte swap or shift outputBuffer to convert it to
-        host format, do it here.
-    */
-
-    PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
-
-
-    if( callbackResult == paContinue )
-    {
-        /* nothing special to do */
-    }
-    else if( callbackResult == paAbort )
-    {
-        /* IMPLEMENT ME - finish playback immediately  */
-
-        /* once finished, call the finished callback */
-        if( stream->streamRepresentation.streamFinishedCallback != 0 )
-            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
-    }
-    else
-    {
-        /* User callback has asked us to stop with paComplete or other non-zero value */
-
-        /* IMPLEMENT ME - finish playback once currently queued audio has completed  */
-
-        /* once finished, call the finished callback */
-        if( stream->streamRepresentation.streamFinishedCallback != 0 )
-            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
-    }
-}
-
-
-void 
-MMCSS_activate(){
-
-    DWORD stuff=0;
-    HANDLE thCarac = pAvSetMmThreadCharacteristics("Pro Audio",&stuff);
-    if (!thCarac){
-        PRINT(("AvSetMmThreadCharacteristics failed!\n"));
-    }
-
-    BOOL prio = pAvSetMmThreadPriority(thCarac,AVRT_PRIORITY_NORMAL);
-    if (!prio){
-        PRINT(("AvSetMmThreadPriority failed!\n"));
-    }
-
-	//debug
-    {
-        HANDLE hh       = GetCurrentThread();
-        int  currprio   = GetThreadPriority(hh);
-        DWORD currclass = GetPriorityClass(GetCurrentProcess());
-        PRINT(("currprio 0x%X currclass 0x%X\n",currprio,currclass));
-    }
-}
-
-
-VOID
-ProcThread(void* param){
-	HRESULT hResult;
-	MMCSS_activate();
-
-    PaWinWasapiStream *stream = (PaWinWasapiStream*)param;
-
-	stream->hNotificationEvent = CreateEvent(NULL, 
-	                                         FALSE,  //bManualReset are we sure??
-											 FALSE, 
-											 "PAWASA");
-	hResult = stream->out.client->SetEventHandle(stream->hNotificationEvent);
-	if (hResult != S_OK)
-		logAUDCLNT_E(hResult);
-
-	if (stream->out.client){
-		hResult = stream->out.client->Start();
-		if (hResult != S_OK)
-			logAUDCLNT_E(hResult);
-	}
-
-	stream->running = true;
-	bool bOne = false;
-
-	while( !stream->closeRequest ) 
-    { 
-	    //lets wait but have a 1 second timeout
-        DWORD dwResult = WaitForSingleObject(stream->hNotificationEvent, 1000);
-        switch( dwResult ) {
-		case WAIT_OBJECT_0: {
-
-			unsigned long usingBS = stream->out.framesPerHostCallback;
-
-			BYTE* indata  = 0;
-			BYTE* outdata = 0;
-
-			hResult = stream->rclient->GetBuffer(usingBS, &outdata);
-
-			if (hResult != S_OK || !outdata) {
-				//logAUDCLNT_E(hResult);
-				//most probably shared mode and hResult=AUDCLNT_E_BUFFER_TOO_LARGE
-				UINT32 padding = 0;
-				hResult = stream->out.client->GetCurrentPadding(&padding);
-				if (padding == 0)
-					break;	
-				usingBS = usingBS-padding;
-				if (usingBS == 0)
-					break;//huh?
-				hResult = stream->rclient->GetBuffer(usingBS, &outdata);
-				if (hResult != S_OK)//what can we do NOW??
-					break;
-				//logAUDCLNT_E(hResult);			
-			}
-	
-			WaspiHostProcessingLoop(indata, usingBS ,outdata, usingBS, stream);
-
-			hResult = stream->rclient->ReleaseBuffer(usingBS, 0);
-			if (hResult != S_OK)
-				logAUDCLNT_E(hResult);
-
-			 /*	This was suggested, but in my tests it doesnt seem to improve the 
-                locking behaviour some drivers have running in exclusive mode.
-                if(!ResetEvent(stream->hNotificationEvent)){
-					logAUDCLNT_E(hResult);
-				}
-             */
-
-		} 
-		break;
-
-        }
-    }
-	stream->out.client->Stop();
-    stream->closeRequest = false;
-}
-
-
-
-
-#endif //VC 2005
-
-
-
-
-#if 0
-			if(bFirst) {			
-				float masteur;
-				hResult = stream->outVol->GetMasterVolumeLevelScalar(&masteur);
-				if (hResult != S_OK)
-					logAUDCLNT_E(hResult);
-				float chan1, chan2;
-				hResult = stream->outVol->GetChannelVolumeLevelScalar(0, &chan1);
-				if (hResult != S_OK)
-					logAUDCLNT_E(hResult);
-				hResult = stream->outVol->GetChannelVolumeLevelScalar(1, &chan2);
-				if (hResult != S_OK)
-					logAUDCLNT_E(hResult);
-
-				BOOL bMute;
-				hResult = stream->outVol->GetMute(&bMute);
-				if (hResult != S_OK)
-					logAUDCLNT_E(hResult);
-
-				stream->outVol->SetMasterVolumeLevelScalar(0.5, NULL);
-				stream->outVol->SetChannelVolumeLevelScalar(0, 0.5, NULL);
-				stream->outVol->SetChannelVolumeLevelScalar(1, 0.5, NULL);
-				stream->outVol->SetMute(FALSE, NULL);
-				bFirst = false;
-			}
-#endif
\ No newline at end of file
diff --git a/portaudio/unused/hostapi/wdmks/pa_win_wdmks.c b/portaudio/unused/hostapi/wdmks/pa_win_wdmks.c
deleted file mode 100644
index aad156b7365430f363434905845af94875ecfc9c..0000000000000000000000000000000000000000
--- a/portaudio/unused/hostapi/wdmks/pa_win_wdmks.c
+++ /dev/null
@@ -1,3278 +0,0 @@
-/*
- * $Id: pa_win_wdmks.c 1229 2007-06-15 16:11:11Z rossb $
- * PortAudio Windows WDM-KS interface
- *
- * Author: Andrew Baldwin
- * Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2004 Andrew Baldwin, Ross Bencina, Phil Burk
- *
- * 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
- @ingroup hostaip_src
- @brief Portaudio WDM-KS host API.
-
- @note This is the implementation of the Portaudio host API using the
- Windows WDM/Kernel Streaming API in order to enable very low latency
- playback and recording on all modern Windows platforms (e.g. 2K, XP)
- Note: This API accesses the device drivers below the usual KMIXER
- component which is normally used to enable multi-client mixing and
- format conversion. That means that it will lock out all other users
- of a device for the duration of active stream using those devices
-*/
-
-#include <stdio.h>
-
-/* Debugging/tracing support */
-
-#define PA_LOGE_
-#define PA_LOGL_
-
-#ifdef __GNUC__
-    #include <initguid.h>
-    #define _WIN32_WINNT 0x0501
-    #define WINVER 0x0501
-#endif
-
-#include <string.h> /* strlen() */
-#include <assert.h>
-
-#include "pa_util.h"
-#include "pa_allocation.h"
-#include "pa_hostapi.h"
-#include "pa_stream.h"
-#include "pa_cpuload.h"
-#include "pa_process.h"
-#include "portaudio.h"
-#include "pa_debugprint.h"
-
-#include <windows.h>
-#include <winioctl.h>
-
-
-#ifdef __GNUC__
-    #undef PA_LOGE_
-    #define PA_LOGE_ PA_DEBUG(("%s {\n",__FUNCTION__))
-    #undef PA_LOGL_
-    #define PA_LOGL_ PA_DEBUG(("} %s\n",__FUNCTION__))
-    /* These defines are set in order to allow the WIndows DirectX
-     * headers to compile with a GCC compiler such as MinGW
-     * NOTE: The headers may generate a few warning in GCC, but
-     * they should compile */
-    #define _INC_MMSYSTEM
-    #define _INC_MMREG
-    #define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */
-    #define DEFINE_GUID_THUNK(name,guid) DEFINE_GUID(name,guid)
-    #define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK( n, STATIC_##n )
-    #if !defined( DEFINE_WAVEFORMATEX_GUID )
-        #define DEFINE_WAVEFORMATEX_GUID(x) (USHORT)(x), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
-    #endif
-    #define  WAVE_FORMAT_ADPCM      0x0002
-    #define  WAVE_FORMAT_IEEE_FLOAT 0x0003
-    #define  WAVE_FORMAT_ALAW       0x0006
-    #define  WAVE_FORMAT_MULAW      0x0007
-    #define  WAVE_FORMAT_MPEG       0x0050
-    #define  WAVE_FORMAT_DRM        0x0009
-    #define DYNAMIC_GUID_THUNK(l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-    #define DYNAMIC_GUID(data) DYNAMIC_GUID_THUNK(data)
-#endif
-
-#ifdef _MSC_VER
-    #define DYNAMIC_GUID(data) {data}
-    #define _INC_MMREG
-    #define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */
-    #undef DEFINE_GUID
-    #define DEFINE_GUID(n,data) EXTERN_C const GUID n = {data}
-    #define DEFINE_GUID_THUNK(n,data) DEFINE_GUID(n,data)
-    #define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK(n, STATIC_##n)
-    #if !defined( DEFINE_WAVEFORMATEX_GUID )
-        #define DEFINE_WAVEFORMATEX_GUID(x) (USHORT)(x), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
-    #endif
-    #define  WAVE_FORMAT_ADPCM      0x0002
-    #define  WAVE_FORMAT_IEEE_FLOAT 0x0003
-    #define  WAVE_FORMAT_ALAW       0x0006
-    #define  WAVE_FORMAT_MULAW      0x0007
-    #define  WAVE_FORMAT_MPEG       0x0050
-    #define  WAVE_FORMAT_DRM        0x0009
-#endif
-
-#include <ks.h>
-#include <ksmedia.h>
-#include <tchar.h>
-#include <assert.h>
-#include <stdio.h>
-
-/* These next definitions allow the use of the KSUSER DLL */
-typedef KSDDKAPI DWORD WINAPI KSCREATEPIN(HANDLE, PKSPIN_CONNECT, ACCESS_MASK, PHANDLE);
-extern HMODULE      DllKsUser;
-extern KSCREATEPIN* FunctionKsCreatePin;
-
-/* Forward definition to break circular type reference between pin and filter */
-struct __PaWinWdmFilter;
-typedef struct __PaWinWdmFilter PaWinWdmFilter;
-
-/* The Pin structure
- * A pin is an input or output node, e.g. for audio flow */
-typedef struct __PaWinWdmPin
-{
-    HANDLE                      handle;
-    PaWinWdmFilter*             parentFilter;
-    unsigned long               pinId;
-    KSPIN_CONNECT*              pinConnect;
-    unsigned long               pinConnectSize;
-    KSDATAFORMAT_WAVEFORMATEX*  ksDataFormatWfx;
-    KSPIN_COMMUNICATION         communication;
-    KSDATARANGE*                dataRanges;
-    KSMULTIPLE_ITEM*            dataRangesItem;
-    KSPIN_DATAFLOW              dataFlow;
-    KSPIN_CINSTANCES            instances;
-    unsigned long               frameSize;
-    int                         maxChannels;
-    unsigned long               formats;
-    int                         bestSampleRate;
-}
-PaWinWdmPin;
-
-/* The Filter structure
- * A filter has a number of pins and a "friendly name" */
-struct __PaWinWdmFilter
-{
-    HANDLE         handle;
-    int            pinCount;
-    PaWinWdmPin**  pins;
-    TCHAR          filterName[MAX_PATH];
-    TCHAR          friendlyName[MAX_PATH];
-    int            maxInputChannels;
-    int            maxOutputChannels;
-    unsigned long  formats;
-    int            usageCount;
-    int            bestSampleRate;
-};
-
-/* PaWinWdmHostApiRepresentation - host api datastructure specific to this implementation */
-typedef struct __PaWinWdmHostApiRepresentation
-{
-    PaUtilHostApiRepresentation  inheritedHostApiRep;
-    PaUtilStreamInterface        callbackStreamInterface;
-    PaUtilStreamInterface        blockingStreamInterface;
-
-    PaUtilAllocationGroup*       allocations;
-    PaWinWdmFilter**             filters;
-    int                          filterCount;
-}
-PaWinWdmHostApiRepresentation;
-
-typedef struct __PaWinWdmDeviceInfo
-{
-    PaDeviceInfo     inheritedDeviceInfo;
-    PaWinWdmFilter*  filter;
-}
-PaWinWdmDeviceInfo;
-
-typedef struct __DATAPACKET
-{
-    KSSTREAM_HEADER  Header;
-    OVERLAPPED       Signal;
-} DATAPACKET;
-
-/* PaWinWdmStream - a stream data structure specifically for this implementation */
-typedef struct __PaWinWdmStream
-{
-    PaUtilStreamRepresentation  streamRepresentation;
-    PaUtilCpuLoadMeasurer       cpuLoadMeasurer;
-    PaUtilBufferProcessor       bufferProcessor;
-
-    PaWinWdmPin*                recordingPin;
-    PaWinWdmPin*                playbackPin;
-    char*                       hostBuffer;
-    unsigned long               framesPerHostIBuffer;
-    unsigned long               framesPerHostOBuffer;
-    int                         bytesPerInputFrame;
-    int                         bytesPerOutputFrame;
-    int                         streamStarted;
-    int                         streamActive;
-    int                         streamStop;
-    int                         streamAbort;
-    int                         oldProcessPriority;
-    HANDLE                      streamThread;
-    HANDLE                      events[5];  /* 2 play + 2 record packets + abort events */
-    DATAPACKET                  packets[4]; /* 2 play + 2 record */
-    PaStreamFlags               streamFlags;
-    /* These values handle the case where the user wants to use fewer
-     * channels than the device has */
-    int                         userInputChannels;
-    int                         deviceInputChannels;
-    int                         userOutputChannels;
-    int                         deviceOutputChannels;
-    int                         inputSampleSize;
-    int                         outputSampleSize;
-}
-PaWinWdmStream;
-
-#include <setupapi.h>
-
-HMODULE      DllKsUser = NULL;
-KSCREATEPIN* FunctionKsCreatePin = NULL;
-
-/* prototypes for functions declared in this file */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-/* Low level I/O functions */
-static PaError WdmSyncIoctl(HANDLE handle,
-    unsigned long ioctlNumber,
-    void* inBuffer,
-    unsigned long inBufferCount,
-    void* outBuffer,
-    unsigned long outBufferCount,
-    unsigned long* bytesReturned);
-static PaError WdmGetPropertySimple(HANDLE handle,
-    const GUID* const guidPropertySet,
-    unsigned long property,
-    void* value,
-    unsigned long valueCount,
-    void* instance,
-    unsigned long instanceCount);
-static PaError WdmSetPropertySimple(HANDLE handle,
-    const GUID* const guidPropertySet,
-    unsigned long property,
-    void* value,
-    unsigned long valueCount,
-    void* instance,
-    unsigned long instanceCount);
-static PaError WdmGetPinPropertySimple(HANDLE  handle,
-    unsigned long pinId,
-    const GUID* const guidPropertySet,
-    unsigned long property,
-    void* value,
-    unsigned long valueCount);
-static PaError WdmGetPinPropertyMulti(HANDLE  handle,
-    unsigned long pinId,
-    const GUID* const guidPropertySet,
-    unsigned long property,
-    KSMULTIPLE_ITEM** ksMultipleItem);
-
-/** Pin management functions */
-static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, PaError* error);
-static void PinFree(PaWinWdmPin* pin);
-static void PinClose(PaWinWdmPin* pin);
-static PaError PinInstantiate(PaWinWdmPin* pin);
-/*static PaError PinGetState(PaWinWdmPin* pin, KSSTATE* state); NOT USED */
-static PaError PinSetState(PaWinWdmPin* pin, KSSTATE state);
-static PaError PinSetFormat(PaWinWdmPin* pin, const WAVEFORMATEX* format);
-static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format);
-
-/* Filter management functions */
-static PaWinWdmFilter* FilterNew(
-    TCHAR* filterName,
-    TCHAR* friendlyName,
-    PaError* error);
-static void FilterFree(PaWinWdmFilter* filter);
-static PaWinWdmPin* FilterCreateRenderPin(
-    PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex,
-    PaError* error);
-static PaWinWdmPin* FilterFindViableRenderPin(
-    PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex,
-    PaError* error);
-static PaError FilterCanCreateRenderPin(
-    PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex);
-static PaWinWdmPin* FilterCreateCapturePin(
-    PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex,
-    PaError* error);
-static PaWinWdmPin* FilterFindViableCapturePin(
-    PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex,
-    PaError* error);
-static PaError FilterCanCreateCapturePin(
-    PaWinWdmFilter* filter,
-    const WAVEFORMATEX* pwfx);
-static PaError FilterUse(
-    PaWinWdmFilter* filter);
-static void FilterRelease(
-    PaWinWdmFilter* filter);
-
-/* Interface functions */
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
-static PaError IsFormatSupported(
-    struct PaUtilHostApiRepresentation *hostApi,
-    const PaStreamParameters *inputParameters,
-    const PaStreamParameters *outputParameters,
-    double sampleRate );
-static PaError OpenStream(
-    struct PaUtilHostApiRepresentation *hostApi,
-    PaStream** s,
-    const PaStreamParameters *inputParameters,
-    const PaStreamParameters *outputParameters,
-    double sampleRate,
-    unsigned long framesPerBuffer,
-    PaStreamFlags streamFlags,
-    PaStreamCallback *streamCallback,
-    void *userData );
-static PaError CloseStream( PaStream* stream );
-static PaError StartStream( PaStream *stream );
-static PaError StopStream( PaStream *stream );
-static PaError AbortStream( PaStream *stream );
-static PaError IsStreamStopped( PaStream *s );
-static PaError IsStreamActive( PaStream *stream );
-static PaTime GetStreamTime( PaStream *stream );
-static double GetStreamCpuLoad( PaStream* stream );
-static PaError ReadStream(
-    PaStream* stream,
-    void *buffer,
-    unsigned long frames );
-static PaError WriteStream(
-    PaStream* stream,
-    const void *buffer,
-    unsigned long frames );
-static signed long GetStreamReadAvailable( PaStream* stream );
-static signed long GetStreamWriteAvailable( PaStream* stream );
-
-/* Utility functions */
-static unsigned long GetWfexSize(const WAVEFORMATEX* wfex);
-static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi);
-static BOOL PinWrite(HANDLE h, DATAPACKET* p);
-static BOOL PinRead(HANDLE h, DATAPACKET* p);
-static void DuplicateFirstChannelInt16(void* buffer, int channels, int samples);
-static void DuplicateFirstChannelInt24(void* buffer, int channels, int samples);
-static DWORD WINAPI ProcessingThread(LPVOID pParam);
-
-/* Function bodies */
-
-static unsigned long GetWfexSize(const WAVEFORMATEX* wfex)
-{
-    if( wfex->wFormatTag == WAVE_FORMAT_PCM )
-    {
-        return sizeof( WAVEFORMATEX );
-    }
-    else
-    {
-        return (sizeof( WAVEFORMATEX ) + wfex->cbSize);
-    }
-}
-
-/*
-Low level pin/filter access functions
-*/
-static PaError WdmSyncIoctl(
-    HANDLE handle,
-    unsigned long ioctlNumber,
-    void* inBuffer,
-    unsigned long inBufferCount,
-    void* outBuffer,
-    unsigned long outBufferCount,
-    unsigned long* bytesReturned)
-{
-    PaError result = paNoError;
-    OVERLAPPED overlapped;
-    int boolResult;
-    unsigned long dummyBytesReturned;
-    unsigned long error;
-
-    if( !bytesReturned )
-    {
-        /* User a dummy as the caller hasn't supplied one */
-        bytesReturned = &dummyBytesReturned;
-    }
-
-    FillMemory((void *)&overlapped,sizeof(overlapped),0);
-    overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
-    if( !overlapped.hEvent )
-    {
-          result = paInsufficientMemory;
-        goto error;
-    }
-    overlapped.hEvent = (HANDLE)((DWORD_PTR)overlapped.hEvent | 0x1);
-
-    boolResult = DeviceIoControl(handle, ioctlNumber, inBuffer, inBufferCount,
-        outBuffer, outBufferCount, bytesReturned, &overlapped);
-    if( !boolResult )
-    {
-        error = GetLastError();
-        if( error == ERROR_IO_PENDING )
-        {
-            error = WaitForSingleObject(overlapped.hEvent,INFINITE);
-            if( error != WAIT_OBJECT_0 )
-            {
-                result = paUnanticipatedHostError;
-                goto error;
-            }
-        }
-        else if((( error == ERROR_INSUFFICIENT_BUFFER ) ||
-                  ( error == ERROR_MORE_DATA )) &&
-                  ( ioctlNumber == IOCTL_KS_PROPERTY ) &&
-                  ( outBufferCount == 0 ))
-        {
-            boolResult = TRUE;
-        }
-        else
-        {
-            result = paUnanticipatedHostError;
-        }
-    }
-    if( !boolResult )
-        *bytesReturned = 0;
-
-error:
-    if( overlapped.hEvent )
-    {
-            CloseHandle( overlapped.hEvent );
-    }
-    return result;
-}
-
-static PaError WdmGetPropertySimple(HANDLE handle,
-    const GUID* const guidPropertySet,
-    unsigned long property,
-    void* value,
-    unsigned long valueCount,
-    void* instance,
-    unsigned long instanceCount)
-{
-    PaError result;
-    KSPROPERTY* ksProperty;
-    unsigned long propertyCount;
-
-    propertyCount = sizeof(KSPROPERTY) + instanceCount;
-    ksProperty = (KSPROPERTY*)PaUtil_AllocateMemory( propertyCount );
-    if( !ksProperty )
-    {
-        return paInsufficientMemory;
-    }
-
-    FillMemory((void*)ksProperty,sizeof(ksProperty),0);
-    ksProperty->Set = *guidPropertySet;
-    ksProperty->Id = property;
-    ksProperty->Flags = KSPROPERTY_TYPE_GET;
-
-    if( instance )
-    {
-        memcpy( (void*)(((char*)ksProperty)+sizeof(KSPROPERTY)), instance, instanceCount );
-    }
-
-    result = WdmSyncIoctl(
-                handle,
-                IOCTL_KS_PROPERTY,
-                ksProperty,
-                propertyCount,
-                value,
-                valueCount,
-                NULL);
-
-    PaUtil_FreeMemory( ksProperty );
-    return result;
-}
-
-static PaError WdmSetPropertySimple(
-    HANDLE handle,
-    const GUID* const guidPropertySet,
-    unsigned long property,
-    void* value,
-    unsigned long valueCount,
-    void* instance,
-    unsigned long instanceCount)
-{
-    PaError result;
-    KSPROPERTY* ksProperty;
-    unsigned long propertyCount  = 0;
-
-    propertyCount = sizeof(KSPROPERTY) + instanceCount;
-    ksProperty = (KSPROPERTY*)PaUtil_AllocateMemory( propertyCount );
-    if( !ksProperty )
-    {
-        return paInsufficientMemory;
-    }
-
-    ksProperty->Set = *guidPropertySet;
-    ksProperty->Id = property;
-    ksProperty->Flags = KSPROPERTY_TYPE_SET;
-
-    if( instance )
-    {
-        memcpy((void*)((char*)ksProperty + sizeof(KSPROPERTY)), instance, instanceCount);
-    }
-
-    result = WdmSyncIoctl(
-                handle,
-                IOCTL_KS_PROPERTY,
-                ksProperty,
-                propertyCount,
-                value,
-                valueCount,
-                NULL);
-
-    PaUtil_FreeMemory( ksProperty );
-    return result;
-}
-
-static PaError WdmGetPinPropertySimple(
-    HANDLE  handle,
-    unsigned long pinId,
-    const GUID* const guidPropertySet,
-    unsigned long property,
-    void* value,
-    unsigned long valueCount)
-{
-    PaError result;
-
-    KSP_PIN ksPProp;
-    ksPProp.Property.Set = *guidPropertySet;
-    ksPProp.Property.Id = property;
-    ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
-    ksPProp.PinId = pinId;
-    ksPProp.Reserved = 0;
-
-    result = WdmSyncIoctl(
-                handle,
-                IOCTL_KS_PROPERTY,
-                &ksPProp,
-                sizeof(KSP_PIN),
-                value,
-                valueCount,
-                NULL);
-
-    return result;
-}
-
-static PaError WdmGetPinPropertyMulti(
-    HANDLE handle,
-    unsigned long pinId,
-    const GUID* const guidPropertySet,
-    unsigned long property,
-    KSMULTIPLE_ITEM** ksMultipleItem)
-{
-    PaError result;
-    unsigned long multipleItemSize = 0;
-    KSP_PIN ksPProp;
-
-    ksPProp.Property.Set = *guidPropertySet;
-    ksPProp.Property.Id = property;
-    ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;
-    ksPProp.PinId = pinId;
-    ksPProp.Reserved = 0;
-
-    result = WdmSyncIoctl(
-                handle,
-                IOCTL_KS_PROPERTY,
-                &ksPProp.Property,
-                sizeof(KSP_PIN),
-                NULL,
-                0,
-                &multipleItemSize);
-    if( result != paNoError )
-    {
-        return result;
-    }
-
-    *ksMultipleItem = (KSMULTIPLE_ITEM*)PaUtil_AllocateMemory( multipleItemSize );
-    if( !*ksMultipleItem )
-    {
-        return paInsufficientMemory;
-    }
-
-    result = WdmSyncIoctl(
-                handle,
-                IOCTL_KS_PROPERTY,
-                &ksPProp,
-                sizeof(KSP_PIN),
-                (void*)*ksMultipleItem,
-                multipleItemSize,
-                NULL);
-
-    if( result != paNoError )
-    {
-        PaUtil_FreeMemory( ksMultipleItem );
-    }
-
-    return result;
-}
-
-
-/*
-Create a new pin object belonging to a filter
-The pin object holds all the configuration information about the pin
-before it is opened, and then the handle of the pin after is opened
-*/
-static PaWinWdmPin* PinNew(PaWinWdmFilter* parentFilter, unsigned long pinId, PaError* error)
-{
-    PaWinWdmPin* pin;
-    PaError result;
-    unsigned long i;
-    KSMULTIPLE_ITEM* item = NULL;
-    KSIDENTIFIER* identifier;
-    KSDATARANGE* dataRange;
-
-    PA_LOGE_;
-    PA_DEBUG(("Creating pin %d:\n",pinId));
-
-    /* Allocate the new PIN object */
-    pin = (PaWinWdmPin*)PaUtil_AllocateMemory( sizeof(PaWinWdmPin) );
-    if( !pin )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    /* Zero the pin object */
-    /* memset( (void*)pin, 0, sizeof(PaWinWdmPin) ); */
-
-    pin->parentFilter = parentFilter;
-    pin->pinId = pinId;
-
-    /* Allocate a connect structure */
-    pin->pinConnectSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX);
-    pin->pinConnect = (KSPIN_CONNECT*)PaUtil_AllocateMemory( pin->pinConnectSize );
-    if( !pin->pinConnect )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    /* Configure the connect structure with default values */
-    pin->pinConnect->Interface.Set               = KSINTERFACESETID_Standard;
-    pin->pinConnect->Interface.Id                = KSINTERFACE_STANDARD_STREAMING;
-    pin->pinConnect->Interface.Flags             = 0;
-    pin->pinConnect->Medium.Set                  = KSMEDIUMSETID_Standard;
-    pin->pinConnect->Medium.Id                   = KSMEDIUM_TYPE_ANYINSTANCE;
-    pin->pinConnect->Medium.Flags                = 0;
-    pin->pinConnect->PinId                       = pinId;
-    pin->pinConnect->PinToHandle                 = NULL;
-    pin->pinConnect->Priority.PriorityClass      = KSPRIORITY_NORMAL;
-    pin->pinConnect->Priority.PrioritySubClass   = 1;
-    pin->ksDataFormatWfx = (KSDATAFORMAT_WAVEFORMATEX*)(pin->pinConnect + 1);
-    pin->ksDataFormatWfx->DataFormat.FormatSize  = sizeof(KSDATAFORMAT_WAVEFORMATEX);
-    pin->ksDataFormatWfx->DataFormat.Flags       = 0;
-    pin->ksDataFormatWfx->DataFormat.Reserved    = 0;
-    pin->ksDataFormatWfx->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
-    pin->ksDataFormatWfx->DataFormat.SubFormat   = KSDATAFORMAT_SUBTYPE_PCM;
-    pin->ksDataFormatWfx->DataFormat.Specifier   = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
-
-    pin->frameSize = 0; /* Unknown until we instantiate pin */
-
-    /* Get the COMMUNICATION property */
-    result = WdmGetPinPropertySimple(
-        parentFilter->handle,
-        pinId,
-        &KSPROPSETID_Pin,
-        KSPROPERTY_PIN_COMMUNICATION,
-        &pin->communication,
-        sizeof(KSPIN_COMMUNICATION));
-    if( result != paNoError )
-        goto error;
-
-    if( /*(pin->communication != KSPIN_COMMUNICATION_SOURCE) &&*/
-         (pin->communication != KSPIN_COMMUNICATION_SINK) &&
-         (pin->communication != KSPIN_COMMUNICATION_BOTH) )
-    {
-        PA_DEBUG(("Not source/sink\n"));
-        result = paInvalidDevice;
-        goto error;
-    }
-
-    /* Get dataflow information */
-    result = WdmGetPinPropertySimple(
-        parentFilter->handle,
-        pinId,
-        &KSPROPSETID_Pin,
-        KSPROPERTY_PIN_DATAFLOW,
-        &pin->dataFlow,
-        sizeof(KSPIN_DATAFLOW));
-
-    if( result != paNoError )
-        goto error;
-
-    /* Get the INTERFACE property list */
-    result = WdmGetPinPropertyMulti(
-        parentFilter->handle,
-        pinId,
-        &KSPROPSETID_Pin,
-        KSPROPERTY_PIN_INTERFACES,
-        &item);
-
-    if( result != paNoError )
-        goto error;
-
-    identifier = (KSIDENTIFIER*)(item+1);
-
-    /* Check that at least one interface is STANDARD_STREAMING */
-    result = paUnanticipatedHostError;
-    for( i = 0; i < item->Count; i++ )
-    {
-        if( !memcmp( (void*)&identifier[i].Set, (void*)&KSINTERFACESETID_Standard, sizeof( GUID ) ) &&
-            ( identifier[i].Id == KSINTERFACE_STANDARD_STREAMING ) )
-        {
-            result = paNoError;
-            break;
-        }
-    }
-
-    if( result != paNoError )
-    {
-        PA_DEBUG(("No standard streaming\n"));
-        goto error;
-    }
-
-    /* Don't need interfaces any more */
-    PaUtil_FreeMemory( item );
-    item = NULL;
-
-    /* Get the MEDIUM properties list */
-    result = WdmGetPinPropertyMulti(
-        parentFilter->handle,
-        pinId,
-        &KSPROPSETID_Pin,
-        KSPROPERTY_PIN_MEDIUMS,
-        &item);
-
-    if( result != paNoError )
-        goto error;
-
-    identifier = (KSIDENTIFIER*)(item+1); /* Not actually necessary... */
-
-    /* Check that at least one medium is STANDARD_DEVIO */
-    result = paUnanticipatedHostError;
-    for( i = 0; i < item->Count; i++ )
-    {
-        if( !memcmp( (void*)&identifier[i].Set, (void*)&KSMEDIUMSETID_Standard, sizeof( GUID ) ) &&
-           ( identifier[i].Id == KSMEDIUM_STANDARD_DEVIO ) )
-        {
-            result = paNoError;
-            break;
-        }
-    }
-
-    if( result != paNoError )
-    {
-        PA_DEBUG(("No standard devio\n"));
-        goto error;
-    }
-    /* Don't need mediums any more */
-    PaUtil_FreeMemory( item );
-    item = NULL;
-
-    /* Get DATARANGES */
-    result = WdmGetPinPropertyMulti(
-        parentFilter->handle,
-        pinId,
-        &KSPROPSETID_Pin,
-        KSPROPERTY_PIN_DATARANGES,
-        &pin->dataRangesItem);
-
-    if( result != paNoError )
-        goto error;
-
-    pin->dataRanges = (KSDATARANGE*)(pin->dataRangesItem +1);
-
-    /* Check that at least one datarange supports audio */
-    result = paUnanticipatedHostError;
-    dataRange = pin->dataRanges;
-    pin->maxChannels = 0;
-    pin->bestSampleRate = 0;
-    pin->formats = 0;
-    for( i = 0; i <pin->dataRangesItem->Count; i++)
-    {
-        PA_DEBUG(("DR major format %x\n",*(unsigned long*)(&(dataRange->MajorFormat))));
-        /* Check that subformat is WAVEFORMATEX, PCM or WILDCARD */
-        if( IS_VALID_WAVEFORMATEX_GUID(&dataRange->SubFormat) ||
-            !memcmp((void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_PCM, sizeof ( GUID ) ) ||
-            ( !memcmp((void*)&dataRange->SubFormat, (void*)&KSDATAFORMAT_SUBTYPE_WILDCARD, sizeof ( GUID ) ) &&
-            ( !memcmp((void*)&dataRange->MajorFormat, (void*)&KSDATAFORMAT_TYPE_AUDIO, sizeof ( GUID ) ) ) ) )
-        {
-            result = paNoError;
-            /* Record the maximum possible channels with this pin */
-            PA_DEBUG(("MaxChannel: %d\n",pin->maxChannels));
-            if( (int)((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels > pin->maxChannels )
-            {
-                pin->maxChannels = ((KSDATARANGE_AUDIO*)dataRange)->MaximumChannels;
-                /*PA_DEBUG(("MaxChannel: %d\n",pin->maxChannels));*/
-            }
-            /* Record the formats (bit depths) that are supported */
-            if( ((KSDATARANGE_AUDIO*)dataRange)->MinimumBitsPerSample <= 16 )
-            {
-                pin->formats |= paInt16;
-                PA_DEBUG(("Format 16 bit supported\n"));
-            }
-            if( ((KSDATARANGE_AUDIO*)dataRange)->MaximumBitsPerSample >= 24 )
-            {
-                pin->formats |= paInt24;
-                PA_DEBUG(("Format 24 bit supported\n"));
-            }
-            if( ( pin->bestSampleRate != 48000) &&
-                (((KSDATARANGE_AUDIO*)dataRange)->MaximumSampleFrequency >= 48000) &&
-                (((KSDATARANGE_AUDIO*)dataRange)->MinimumSampleFrequency <= 48000) )
-            {
-                pin->bestSampleRate = 48000;
-                PA_DEBUG(("48kHz supported\n"));
-            }
-            else if(( pin->bestSampleRate != 48000) && ( pin->bestSampleRate != 44100 ) &&
-                (((KSDATARANGE_AUDIO*)dataRange)->MaximumSampleFrequency >= 44100) &&
-                (((KSDATARANGE_AUDIO*)dataRange)->MinimumSampleFrequency <= 44100) )
-            {
-                pin->bestSampleRate = 44100;
-                PA_DEBUG(("44.1kHz supported\n"));
-            }
-            else
-            {
-                pin->bestSampleRate = ((KSDATARANGE_AUDIO*)dataRange)->MaximumSampleFrequency;
-            }
-        }
-        dataRange = (KSDATARANGE*)( ((char*)dataRange) + dataRange->FormatSize);
-    }
-
-    if( result != paNoError )
-        goto error;
-
-    /* Get instance information */
-    result = WdmGetPinPropertySimple(
-        parentFilter->handle,
-        pinId,
-        &KSPROPSETID_Pin,
-        KSPROPERTY_PIN_CINSTANCES,
-        &pin->instances,
-        sizeof(KSPIN_CINSTANCES));
-
-    if( result != paNoError )
-        goto error;
-
-    /* Success */
-    *error = paNoError;
-    PA_DEBUG(("Pin created successfully\n"));
-    PA_LOGL_;
-    return pin;
-
-error:
-    /*
-    Error cleanup
-    */
-    PaUtil_FreeMemory( item );
-    if( pin )
-    {
-        PaUtil_FreeMemory( pin->pinConnect );
-        PaUtil_FreeMemory( pin->dataRangesItem );
-        PaUtil_FreeMemory( pin );
-    }
-    *error = result;
-    PA_LOGL_;
-    return NULL;
-}
-
-/*
-Safely free all resources associated with the pin
-*/
-static void PinFree(PaWinWdmPin* pin)
-{
-    PA_LOGE_;
-    if( pin )
-    {
-        PinClose(pin);
-        if( pin->pinConnect )
-        {
-            PaUtil_FreeMemory( pin->pinConnect );
-        }
-        if( pin->dataRangesItem )
-        {
-            PaUtil_FreeMemory( pin->dataRangesItem );
-        }
-        PaUtil_FreeMemory( pin );
-    }
-    PA_LOGL_;
-}
-
-/*
-If the pin handle is open, close it
-*/
-static void PinClose(PaWinWdmPin* pin)
-{
-    PA_LOGE_;
-    if( pin == NULL )
-    {
-        PA_DEBUG(("Closing NULL pin!"));
-        PA_LOGL_;
-        return;
-    }
-    if( pin->handle != NULL )
-    {
-        PinSetState( pin, KSSTATE_PAUSE );
-        PinSetState( pin, KSSTATE_STOP );
-        CloseHandle( pin->handle );
-        pin->handle = NULL;
-        FilterRelease(pin->parentFilter);
-    }
-    PA_LOGL_;
-}
-
-/*
-Set the state of this (instantiated) pin
-*/
-static PaError PinSetState(PaWinWdmPin* pin, KSSTATE state)
-{
-    PaError result;
-
-    PA_LOGE_;
-    if( pin == NULL )
-        return paInternalError;
-    if( pin->handle == NULL )
-        return paInternalError;
-
-    result = WdmSetPropertySimple(
-        pin->handle,
-        &KSPROPSETID_Connection,
-        KSPROPERTY_CONNECTION_STATE,
-        &state,
-        sizeof(state),
-        NULL,
-        0);
-    PA_LOGL_;
-    return result;
-}
-
-static PaError PinInstantiate(PaWinWdmPin* pin)
-{
-    PaError result;
-    unsigned long createResult;
-    KSALLOCATOR_FRAMING ksaf;
-    KSALLOCATOR_FRAMING_EX ksafex;
-
-    PA_LOGE_;
-
-    if( pin == NULL )
-        return paInternalError;
-    if(!pin->pinConnect)
-        return paInternalError;
-
-    FilterUse(pin->parentFilter);
-
-    createResult = FunctionKsCreatePin(
-        pin->parentFilter->handle,
-        pin->pinConnect,
-        GENERIC_WRITE | GENERIC_READ,
-        &pin->handle
-        );
-
-    PA_DEBUG(("Pin create result = %x\n",createResult));
-    if( createResult != ERROR_SUCCESS )
-    {
-        FilterRelease(pin->parentFilter);
-        pin->handle = NULL;
-        return paInvalidDevice;
-    }
-
-    result = WdmGetPropertySimple(
-        pin->handle,
-        &KSPROPSETID_Connection,
-        KSPROPERTY_CONNECTION_ALLOCATORFRAMING,
-        &ksaf,
-        sizeof(ksaf),
-        NULL,
-        0);
-
-    if( result != paNoError )
-    {
-        result = WdmGetPropertySimple(
-            pin->handle,
-            &KSPROPSETID_Connection,
-            KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX,
-            &ksafex,
-            sizeof(ksafex),
-            NULL,
-            0);
-        if( result == paNoError )
-        {
-            pin->frameSize = ksafex.FramingItem[0].FramingRange.Range.MinFrameSize;
-        }
-    }
-    else
-    {
-        pin->frameSize = ksaf.FrameSize;
-    }
-
-    PA_LOGL_;
-
-    return paNoError;
-}
-
-/* NOT USED
-static PaError PinGetState(PaWinWdmPin* pin, KSSTATE* state)
-{
-    PaError result;
-
-    if( state == NULL )
-        return paInternalError;
-    if( pin == NULL )
-        return paInternalError;
-    if( pin->handle == NULL )
-        return paInternalError;
-
-    result = WdmGetPropertySimple(
-        pin->handle,
-        KSPROPSETID_Connection,
-        KSPROPERTY_CONNECTION_STATE,
-        state,
-        sizeof(KSSTATE),
-        NULL,
-        0);
-
-    return result;
-}
-*/
-static PaError PinSetFormat(PaWinWdmPin* pin, const WAVEFORMATEX* format)
-{
-    unsigned long size;
-    void* newConnect;
-
-    PA_LOGE_;
-
-    if( pin == NULL )
-        return paInternalError;
-    if( format == NULL )
-        return paInternalError;
-
-    size = GetWfexSize(format) + sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX) - sizeof(WAVEFORMATEX);
-
-    if( pin->pinConnectSize != size )
-    {
-        newConnect = PaUtil_AllocateMemory( size );
-        if( newConnect == NULL )
-            return paInsufficientMemory;
-        memcpy( newConnect, (void*)pin->pinConnect, min(pin->pinConnectSize,size) );
-        PaUtil_FreeMemory( pin->pinConnect );
-        pin->pinConnect = (KSPIN_CONNECT*)newConnect;
-        pin->pinConnectSize = size;
-        pin->ksDataFormatWfx = (KSDATAFORMAT_WAVEFORMATEX*)((KSPIN_CONNECT*)newConnect + 1);
-        pin->ksDataFormatWfx->DataFormat.FormatSize = size - sizeof(KSPIN_CONNECT);
-    }
-
-    memcpy( (void*)&(pin->ksDataFormatWfx->WaveFormatEx), format, GetWfexSize(format) );
-    pin->ksDataFormatWfx->DataFormat.SampleSize = (unsigned short)(format->nChannels * (format->wBitsPerSample / 8));
-
-    PA_LOGL_;
-
-    return paNoError;
-}
-
-static PaError PinIsFormatSupported(PaWinWdmPin* pin, const WAVEFORMATEX* format)
-{
-    KSDATARANGE_AUDIO* dataRange;
-    unsigned long count;
-    GUID guid = DYNAMIC_GUID( DEFINE_WAVEFORMATEX_GUID(format->wFormatTag) );
-    PaError result = paInvalidDevice;
-
-    PA_LOGE_;
-
-    if( format->wFormatTag == WAVE_FORMAT_EXTENSIBLE )
-    {
-        guid = ((WAVEFORMATEXTENSIBLE*)format)->SubFormat;
-    }
-    dataRange = (KSDATARANGE_AUDIO*)pin->dataRanges;
-    for(count = 0; count<pin->dataRangesItem->Count; count++)
-    {
-        if(( !memcmp(&(dataRange->DataRange.MajorFormat),&KSDATAFORMAT_TYPE_AUDIO,sizeof(GUID)) ) ||
-           ( !memcmp(&(dataRange->DataRange.MajorFormat),&KSDATAFORMAT_TYPE_WILDCARD,sizeof(GUID)) ))
-        {
-            /* This is an audio or wildcard datarange... */
-            if(( !memcmp(&(dataRange->DataRange.SubFormat),&KSDATAFORMAT_SUBTYPE_WILDCARD,sizeof(GUID)) ) ||
-                ( !memcmp(&(dataRange->DataRange.SubFormat),&guid,sizeof(GUID)) ))
-            {
-                if(( !memcmp(&(dataRange->DataRange.Specifier),&KSDATAFORMAT_SPECIFIER_WILDCARD,sizeof(GUID)) ) ||
-                  ( !memcmp(&(dataRange->DataRange.Specifier),&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,sizeof(GUID) )))
-                {
-
-                    PA_DEBUG(("Pin:%x, DataRange:%d\n",(void*)pin,count));
-                    PA_DEBUG(("\tFormatSize:%d, SampleSize:%d\n",dataRange->DataRange.FormatSize,dataRange->DataRange.SampleSize));
-                    PA_DEBUG(("\tMaxChannels:%d\n",dataRange->MaximumChannels));
-                    PA_DEBUG(("\tBits:%d-%d\n",dataRange->MinimumBitsPerSample,dataRange->MaximumBitsPerSample));
-                    PA_DEBUG(("\tSampleRate:%d-%d\n",dataRange->MinimumSampleFrequency,dataRange->MaximumSampleFrequency));
-
-                    if( dataRange->MaximumChannels < format->nChannels )
-                    {
-                        result = paInvalidChannelCount;
-                        continue;
-                    }
-                    if( dataRange->MinimumBitsPerSample > format->wBitsPerSample )
-                    {
-                        result = paSampleFormatNotSupported;
-                        continue;
-                    }
-                    if( dataRange->MaximumBitsPerSample < format->wBitsPerSample )
-                    {
-                        result = paSampleFormatNotSupported;
-                        continue;
-                    }
-                    if( dataRange->MinimumSampleFrequency > format->nSamplesPerSec )
-                    {
-                        result = paInvalidSampleRate;
-                        continue;
-                    }
-                    if( dataRange->MaximumSampleFrequency < format->nSamplesPerSec )
-                    {
-                        result = paInvalidSampleRate;
-                        continue;
-                    }
-                    /* Success! */
-                    PA_LOGL_;
-                    return paNoError;
-                }
-            }
-        }
-        dataRange = (KSDATARANGE_AUDIO*)( ((char*)dataRange) + dataRange->DataRange.FormatSize);
-    }
-
-    PA_LOGL_;
-
-    return result;
-}
-
-/**
- * Create a new filter object
- */
-static PaWinWdmFilter* FilterNew(TCHAR* filterName, TCHAR* friendlyName, PaError* error)
-{
-    PaWinWdmFilter* filter;
-    PaError result;
-    int pinId;
-    int valid;
-
-
-    /* Allocate the new filter object */
-    filter = (PaWinWdmFilter*)PaUtil_AllocateMemory( sizeof(PaWinWdmFilter) );
-    if( !filter )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    /* Zero the filter object - done by AllocateMemory */
-    /* memset( (void*)filter, 0, sizeof(PaWinWdmFilter) ); */
-
-    /* Copy the filter name */
-    _tcsncpy(filter->filterName, filterName, MAX_PATH);
-
-    /* Copy the friendly name */
-    _tcsncpy(filter->friendlyName, friendlyName, MAX_PATH);
-
-    /* Open the filter handle */
-    result = FilterUse(filter);
-    if( result != paNoError )
-    {
-        goto error;
-    }
-
-    /* Get pin count */
-    result = WdmGetPinPropertySimple
-        (
-        filter->handle,
-        0,
-        &KSPROPSETID_Pin,
-        KSPROPERTY_PIN_CTYPES,
-        &filter->pinCount,
-        sizeof(filter->pinCount)
-        );
-
-    if( result != paNoError)
-    {
-        goto error;
-    }
-
-    /* Allocate pointer array to hold the pins */
-    filter->pins = (PaWinWdmPin**)PaUtil_AllocateMemory( sizeof(PaWinWdmPin*) * filter->pinCount );
-    if( !filter->pins )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    /* Create all the pins we can */
-    filter->maxInputChannels = 0;
-    filter->maxOutputChannels = 0;
-    filter->bestSampleRate = 0;
-
-    valid = 0;
-    for(pinId = 0; pinId < filter->pinCount; pinId++)
-    {
-        /* Create the pin with this Id */
-        PaWinWdmPin* newPin;
-        newPin = PinNew(filter, pinId, &result);
-        if( result == paInsufficientMemory )
-            goto error;
-        if( newPin != NULL )
-        {
-            filter->pins[pinId] = newPin;
-            valid = 1;
-
-            /* Get the max output channel count */
-            if(( newPin->dataFlow == KSPIN_DATAFLOW_IN ) &&
-                (( newPin->communication == KSPIN_COMMUNICATION_SINK) ||
-                 ( newPin->communication == KSPIN_COMMUNICATION_BOTH)))
-            {
-                if(newPin->maxChannels > filter->maxOutputChannels)
-                    filter->maxOutputChannels = newPin->maxChannels;
-                filter->formats |= newPin->formats;
-            }
-            /* Get the max input channel count */
-            if(( newPin->dataFlow == KSPIN_DATAFLOW_OUT ) &&
-                (( newPin->communication == KSPIN_COMMUNICATION_SINK) ||
-                 ( newPin->communication == KSPIN_COMMUNICATION_BOTH)))
-            {
-                if(newPin->maxChannels > filter->maxInputChannels)
-                    filter->maxInputChannels = newPin->maxChannels;
-                filter->formats |= newPin->formats;
-            }
-
-            if(newPin->bestSampleRate > filter->bestSampleRate)
-            {
-                filter->bestSampleRate = newPin->bestSampleRate;
-            }
-        }
-    }
-
-    if(( filter->maxInputChannels == 0) && ( filter->maxOutputChannels == 0))
-    {
-        /* No input or output... not valid */
-        valid = 0;
-    }
-
-    if( !valid )
-    {
-        /* No valid pin was found on this filter so we destroy it */
-        result = paDeviceUnavailable;
-        goto error;
-    }
-
-    /* Close the filter handle for now
-     * It will be opened later when needed */
-    FilterRelease(filter);
-
-    *error = paNoError;
-    return filter;
-
-error:
-    /*
-    Error cleanup
-    */
-    if( filter )
-    {
-        for( pinId = 0; pinId < filter->pinCount; pinId++ )
-            PinFree(filter->pins[pinId]);
-        PaUtil_FreeMemory( filter->pins );
-        if( filter->handle )
-            CloseHandle( filter->handle );
-        PaUtil_FreeMemory( filter );
-    }
-    *error = result;
-    return NULL;
-}
-
-/**
- * Free a previously created filter
- */
-static void FilterFree(PaWinWdmFilter* filter)
-{
-    int pinId;
-    PA_LOGL_;
-    if( filter )
-    {
-        for( pinId = 0; pinId < filter->pinCount; pinId++ )
-            PinFree(filter->pins[pinId]);
-        PaUtil_FreeMemory( filter->pins );
-        if( filter->handle )
-            CloseHandle( filter->handle );
-        PaUtil_FreeMemory( filter );
-    }
-    PA_LOGE_;
-}
-
-/**
- * Reopen the filter handle if necessary so it can be used
- **/
-static PaError FilterUse(PaWinWdmFilter* filter)
-{
-    assert( filter );
-
-    PA_LOGE_;
-    if( filter->handle == NULL )
-    {
-        /* Open the filter */
-        filter->handle = CreateFile(
-            filter->filterName,
-            GENERIC_READ | GENERIC_WRITE,
-            0,
-            NULL,
-            OPEN_EXISTING,
-            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
-            NULL);
-
-        if( filter->handle == NULL )
-        {
-            return paDeviceUnavailable;
-        }
-    }
-    filter->usageCount++;
-    PA_LOGL_;
-    return paNoError;
-}
-
-/**
- * Release the filter handle if nobody is using it
- **/
-static void FilterRelease(PaWinWdmFilter* filter)
-{
-    assert( filter );
-    assert( filter->usageCount > 0 );
-
-    PA_LOGE_;
-    filter->usageCount--;
-    if( filter->usageCount == 0 )
-    {
-        if( filter->handle != NULL )
-        {
-            CloseHandle( filter->handle );
-            filter->handle = NULL;
-        }
-    }
-    PA_LOGL_;
-}
-
-/**
- * Create a render (playback) Pin using the supplied format
- **/
-static PaWinWdmPin* FilterCreateRenderPin(PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex,
-    PaError* error)
-{
-    PaError result;
-    PaWinWdmPin* pin;
-
-    assert( filter );
-
-    pin = FilterFindViableRenderPin(filter,wfex,&result);
-    if(!pin)
-    {
-        goto error;
-    }
-    result = PinSetFormat(pin,wfex);
-    if( result != paNoError )
-    {
-        goto error;
-    }
-    result = PinInstantiate(pin);
-    if( result != paNoError )
-    {
-        goto error;
-    }
-
-    *error = paNoError;
-    return pin;
-
-error:
-    *error = result;
-    return NULL;
-}
-
-/**
- * Find a pin that supports the given format
- **/
-static PaWinWdmPin* FilterFindViableRenderPin(PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex,
-    PaError* error)
-{
-    int pinId;
-    PaWinWdmPin*  pin;
-    PaError result = paDeviceUnavailable;
-    *error = paNoError;
-
-    assert( filter );
-
-    for( pinId = 0; pinId<filter->pinCount; pinId++ )
-    {
-        pin = filter->pins[pinId];
-        if( pin != NULL )
-        {
-            if(( pin->dataFlow == KSPIN_DATAFLOW_IN ) &&
-                (( pin->communication == KSPIN_COMMUNICATION_SINK) ||
-                 ( pin->communication == KSPIN_COMMUNICATION_BOTH)))
-            {
-                result = PinIsFormatSupported( pin, wfex );
-                if( result == paNoError )
-                {
-                    return pin;
-                }
-            }
-        }
-    }
-
-    *error = result;
-    return NULL;
-}
-
-/**
- * Check if there is a pin that should playback
- * with the supplied format
- **/
-static PaError FilterCanCreateRenderPin(PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex)
-{
-    PaWinWdmPin* pin;
-    PaError result;
-
-    assert ( filter );
-
-    pin = FilterFindViableRenderPin(filter,wfex,&result);
-    /* result will be paNoError if pin found
-     * or else an error code indicating what is wrong with the format
-     **/
-    return result;
-}
-
-/**
- * Create a capture (record) Pin using the supplied format
- **/
-static PaWinWdmPin* FilterCreateCapturePin(PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex,
-    PaError* error)
-{
-    PaError result;
-    PaWinWdmPin* pin;
-
-    assert( filter );
-
-    pin = FilterFindViableCapturePin(filter,wfex,&result);
-    if(!pin)
-    {
-        goto error;
-    }
-
-    result = PinSetFormat(pin,wfex);
-    if( result != paNoError )
-    {
-        goto error;
-    }
-
-    result = PinInstantiate(pin);
-    if( result != paNoError )
-    {
-        goto error;
-    }
-
-    *error = paNoError;
-    return pin;
-
-error:
-    *error = result;
-    return NULL;
-}
-
-/**
- * Find a capture pin that supports the given format
- **/
-static PaWinWdmPin* FilterFindViableCapturePin(PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex,
-    PaError* error)
-{
-    int pinId;
-    PaWinWdmPin*  pin;
-    PaError result = paDeviceUnavailable;
-    *error = paNoError;
-
-    assert( filter );
-
-    for( pinId = 0; pinId<filter->pinCount; pinId++ )
-    {
-        pin = filter->pins[pinId];
-        if( pin != NULL )
-        {
-            if(( pin->dataFlow == KSPIN_DATAFLOW_OUT ) &&
-                (( pin->communication == KSPIN_COMMUNICATION_SINK) ||
-                 ( pin->communication == KSPIN_COMMUNICATION_BOTH)))
-            {
-                result = PinIsFormatSupported( pin, wfex );
-                if( result == paNoError )
-                {
-                    return pin;
-                }
-            }
-        }
-    }
-
-    *error = result;
-    return NULL;
-}
-
-/**
- * Check if there is a pin that should playback
- * with the supplied format
- **/
-static PaError FilterCanCreateCapturePin(PaWinWdmFilter* filter,
-    const WAVEFORMATEX* wfex)
-{
-    PaWinWdmPin* pin;
-    PaError result;
-
-    assert ( filter );
-
-    pin = FilterFindViableCapturePin(filter,wfex,&result);
-    /* result will be paNoError if pin found
-     * or else an error code indicating what is wrong with the format
-     **/
-    return result;
-}
-
-/**
- * Build the list of available filters
- */
-static PaError BuildFilterList(PaWinWdmHostApiRepresentation* wdmHostApi)
-{
-    PaError result = paNoError;
-    HDEVINFO handle = NULL;
-    int device;
-    int invalidDevices;
-    int slot;
-    SP_DEVICE_INTERFACE_DATA interfaceData;
-    SP_DEVICE_INTERFACE_DATA aliasData;
-    SP_DEVINFO_DATA devInfoData;
-    int noError;
-    const int sizeInterface = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR));
-    unsigned char interfaceDetailsArray[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR))];
-    SP_DEVICE_INTERFACE_DETAIL_DATA* devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA*)interfaceDetailsArray;
-    TCHAR friendlyName[MAX_PATH];
-    HKEY hkey;
-    DWORD sizeFriendlyName;
-    DWORD type;
-    PaWinWdmFilter* newFilter;
-    GUID* category = (GUID*)&KSCATEGORY_AUDIO;
-    GUID* alias_render = (GUID*)&KSCATEGORY_RENDER;
-    GUID* alias_capture = (GUID*)&KSCATEGORY_CAPTURE;
-    DWORD hasAlias;
-
-    PA_LOGE_;
-
-    devInterfaceDetails->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
-
-    /* Open a handle to search for devices (filters) */
-    handle = SetupDiGetClassDevs(category,NULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
-    if( handle == NULL )
-    {
-        return paUnanticipatedHostError;
-    }
-    PA_DEBUG(("Setup called\n"));
-
-    /* First let's count the number of devices so we can allocate a list */
-    invalidDevices = 0;
-    for( device = 0;;device++ )
-    {
-        interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-        interfaceData.Reserved = 0;
-        aliasData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-        aliasData.Reserved = 0;
-        noError = SetupDiEnumDeviceInterfaces(handle,NULL,category,device,&interfaceData);
-        PA_DEBUG(("Enum called\n"));
-        if( !noError )
-            break; /* No more devices */
-
-        /* Check this one has the render or capture alias */
-        hasAlias = 0;
-        noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_render,&aliasData);
-        PA_DEBUG(("noError = %d\n",noError));
-        if(noError)
-        {
-            if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED)))
-            {
-                PA_DEBUG(("Device %d has render alias\n",device));
-                hasAlias |= 1; /* Has render alias */
-            }
-            else
-            {
-                PA_DEBUG(("Device %d has no render alias\n",device));
-            }
-        }
-        noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_capture,&aliasData);
-        if(noError)
-        {
-            if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED)))
-            {
-                PA_DEBUG(("Device %d has capture alias\n",device));
-                hasAlias |= 2; /* Has capture alias */
-            }
-            else
-            {
-                PA_DEBUG(("Device %d has no capture alias\n",device));
-            }
-        }
-        if(!hasAlias)
-            invalidDevices++; /* This was not a valid capture or render audio device */
-
-    }
-    /* Remember how many there are */
-    wdmHostApi->filterCount = device-invalidDevices;
-
-    PA_DEBUG(("Interfaces found: %d\n",device-invalidDevices));
-
-    /* Now allocate the list of pointers to devices */
-    wdmHostApi->filters  = (PaWinWdmFilter**)PaUtil_AllocateMemory( sizeof(PaWinWdmFilter*) * device );
-    if( !wdmHostApi->filters )
-    {
-        if(handle != NULL)
-            SetupDiDestroyDeviceInfoList(handle);
-        return paInsufficientMemory;
-    }
-
-    /* Now create filter objects for each interface found */
-    slot = 0;
-    for( device = 0;;device++ )
-    {
-        interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-        interfaceData.Reserved = 0;
-        aliasData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-        aliasData.Reserved = 0;
-        devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
-        devInfoData.Reserved = 0;
-
-        noError = SetupDiEnumDeviceInterfaces(handle,NULL,category,device,&interfaceData);
-        if( !noError )
-            break; /* No more devices */
-
-        /* Check this one has the render or capture alias */
-        hasAlias = 0;
-        noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_render,&aliasData);
-        if(noError)
-        {
-            if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED)))
-            {
-                PA_DEBUG(("Device %d has render alias\n",device));
-                hasAlias |= 1; /* Has render alias */
-            }
-        }
-        noError = SetupDiGetDeviceInterfaceAlias(handle,&interfaceData,alias_capture,&aliasData);
-        if(noError)
-        {
-            if(aliasData.Flags && (!(aliasData.Flags & SPINT_REMOVED)))
-            {
-                PA_DEBUG(("Device %d has capture alias\n",device));
-                hasAlias |= 2; /* Has capture alias */
-            }
-        }
-        if(!hasAlias)
-            continue; /* This was not a valid capture or render audio device */
-
-        noError = SetupDiGetDeviceInterfaceDetail(handle,&interfaceData,devInterfaceDetails,sizeInterface,NULL,&devInfoData);
-        if( noError )
-        {
-            /* Try to get the "friendly name" for this interface */
-            sizeFriendlyName = sizeof(friendlyName);
-            /* Fix contributed by Ben Allison
-             * Removed KEY_SET_VALUE from flags on following call
-             * as its causes failure when running without admin rights
-             * and it was not required */
-            hkey=SetupDiOpenDeviceInterfaceRegKey(handle,&interfaceData,0,KEY_QUERY_VALUE);
-            if(hkey!=INVALID_HANDLE_VALUE)
-            {
-                noError = RegQueryValueEx(hkey,TEXT("FriendlyName"),0,&type,(BYTE*)friendlyName,&sizeFriendlyName);
-                if( noError == ERROR_SUCCESS )
-                {
-                    PA_DEBUG(("Interface %d, Name: %s\n",device,friendlyName));
-                    RegCloseKey(hkey);
-                }
-                else
-                {
-                    friendlyName[0] = 0;
-                }
-            }
-            newFilter = FilterNew(devInterfaceDetails->DevicePath,friendlyName,&result);
-            if( result == paNoError )
-            {
-                PA_DEBUG(("Filter created\n"));
-                wdmHostApi->filters[slot] = newFilter;
-                slot++;
-            }
-            else
-            {
-                PA_DEBUG(("Filter NOT created\n"));
-                /* As there are now less filters than we initially thought
-                 * we must reduce the count by one */
-                wdmHostApi->filterCount--;
-            }
-        }
-    }
-
-    /* Clean up */
-    if(handle != NULL)
-        SetupDiDestroyDeviceInfoList(handle);
-
-    return paNoError;
-}
-
-PaError PaWinWdm_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
-{
-    PaError result = paNoError;
-    int i, deviceCount;
-    PaWinWdmHostApiRepresentation *wdmHostApi;
-    PaWinWdmDeviceInfo *deviceInfoArray;
-    PaWinWdmFilter* pFilter;
-    PaWinWdmDeviceInfo *wdmDeviceInfo;
-    PaDeviceInfo *deviceInfo;
-
-    PA_LOGE_;
-
-    /*
-    Attempt to load the KSUSER.DLL without which we cannot create pins
-    We will unload this on termination
-    */
-    if(DllKsUser == NULL)
-    {
-        DllKsUser = LoadLibrary(TEXT("ksuser.dll"));
-        if(DllKsUser == NULL)
-            goto error;
-    }
-
-    FunctionKsCreatePin = (KSCREATEPIN*)GetProcAddress(DllKsUser, "KsCreatePin");
-    if(FunctionKsCreatePin == NULL)
-        goto error;
-
-    wdmHostApi = (PaWinWdmHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinWdmHostApiRepresentation) );
-    if( !wdmHostApi )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    wdmHostApi->allocations = PaUtil_CreateAllocationGroup();
-    if( !wdmHostApi->allocations )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-
-    result = BuildFilterList( wdmHostApi );
-    if( result != paNoError )
-    {
-        goto error;
-    }
-    deviceCount = wdmHostApi->filterCount;
-
-    *hostApi = &wdmHostApi->inheritedHostApiRep;
-    (*hostApi)->info.structVersion = 1;
-    (*hostApi)->info.type = paWDMKS;
-    (*hostApi)->info.name = "Windows WDM-KS";
-    (*hostApi)->info.defaultInputDevice = paNoDevice;
-    (*hostApi)->info.defaultOutputDevice = paNoDevice;
-
-    if( deviceCount > 0 )
-    {
-        (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
-               wdmHostApi->allocations, sizeof(PaWinWdmDeviceInfo*) * deviceCount );
-        if( !(*hostApi)->deviceInfos )
-        {
-            result = paInsufficientMemory;
-            goto error;
-        }
-
-        /* allocate all device info structs in a contiguous block */
-        deviceInfoArray = (PaWinWdmDeviceInfo*)PaUtil_GroupAllocateMemory(
-                wdmHostApi->allocations, sizeof(PaWinWdmDeviceInfo) * deviceCount );
-        if( !deviceInfoArray )
-        {
-            result = paInsufficientMemory;
-            goto error;
-        }
-
-        for( i=0; i < deviceCount; ++i )
-        {
-            wdmDeviceInfo = &deviceInfoArray[i];
-            deviceInfo = &wdmDeviceInfo->inheritedDeviceInfo;
-            pFilter = wdmHostApi->filters[i];
-            if( pFilter == NULL )
-                continue;
-            wdmDeviceInfo->filter = pFilter;
-            deviceInfo->structVersion = 2;
-            deviceInfo->hostApi = hostApiIndex;
-            deviceInfo->name = (char*)pFilter->friendlyName;
-            PA_DEBUG(("Device found name: %s\n",(char*)pFilter->friendlyName));
-            deviceInfo->maxInputChannels = pFilter->maxInputChannels;
-            if(deviceInfo->maxInputChannels > 0)
-            {
-                /* Set the default input device to the first device we find with
-                 * more than zero input channels
-                 **/
-                if((*hostApi)->info.defaultInputDevice == paNoDevice)
-                {
-                    (*hostApi)->info.defaultInputDevice = i;
-                }
-            }
-
-            deviceInfo->maxOutputChannels = pFilter->maxOutputChannels;
-            if(deviceInfo->maxOutputChannels > 0)
-            {
-                /* Set the default output device to the first device we find with
-                 * more than zero output channels
-                 **/
-                if((*hostApi)->info.defaultOutputDevice == paNoDevice)
-                {
-                    (*hostApi)->info.defaultOutputDevice = i;
-                }
-            }
-
-            /* These low values are not very useful because
-             * a) The lowest latency we end up with can depend on many factors such
-             *    as the device buffer sizes/granularities, sample rate, channels and format
-             * b) We cannot know the device buffer sizes until we try to open/use it at
-             *    a particular setting
-             * So: we give 512x48000Hz frames as the default low input latency
-             **/
-            deviceInfo->defaultLowInputLatency = (512.0/48000.0);
-            deviceInfo->defaultLowOutputLatency = (512.0/48000.0);
-            deviceInfo->defaultHighInputLatency = (4096.0/48000.0);
-            deviceInfo->defaultHighOutputLatency = (4096.0/48000.0);
-            deviceInfo->defaultSampleRate = (double)(pFilter->bestSampleRate);
-
-            (*hostApi)->deviceInfos[i] = deviceInfo;
-        }
-    }
-
-    (*hostApi)->info.deviceCount = deviceCount;
-
-    (*hostApi)->Terminate = Terminate;
-    (*hostApi)->OpenStream = OpenStream;
-    (*hostApi)->IsFormatSupported = IsFormatSupported;
-
-    PaUtil_InitializeStreamInterface( &wdmHostApi->callbackStreamInterface, CloseStream, StartStream,
-                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
-                                      GetStreamTime, GetStreamCpuLoad,
-                                      PaUtil_DummyRead, PaUtil_DummyWrite,
-                                      PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
-
-    PaUtil_InitializeStreamInterface( &wdmHostApi->blockingStreamInterface, CloseStream, StartStream,
-                                      StopStream, AbortStream, IsStreamStopped, IsStreamActive,
-                                      GetStreamTime, PaUtil_DummyGetCpuLoad,
-                                      ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
-
-    PA_LOGL_;
-    return result;
-
-error:
-    if( DllKsUser != NULL )
-    {
-        FreeLibrary( DllKsUser );
-        DllKsUser = NULL;
-    }
-
-    if( wdmHostApi )
-    {
-        PaUtil_FreeMemory( wdmHostApi->filters );
-        if( wdmHostApi->allocations )
-        {
-            PaUtil_FreeAllAllocations( wdmHostApi->allocations );
-            PaUtil_DestroyAllocationGroup( wdmHostApi->allocations );
-        }
-        PaUtil_FreeMemory( wdmHostApi );
-    }
-    PA_LOGL_;
-    return result;
-}
-
-
-static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
-{
-    PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
-    int i;
-    PA_LOGE_;
-
-    if( wdmHostApi->filters )
-    {
-        for( i=0; i<wdmHostApi->filterCount; i++)
-        {
-            if( wdmHostApi->filters[i] != NULL )
-            {
-                FilterFree( wdmHostApi->filters[i] );
-                wdmHostApi->filters[i] = NULL;
-            }
-        }
-    }
-    PaUtil_FreeMemory( wdmHostApi->filters );
-    if( wdmHostApi->allocations )
-    {
-        PaUtil_FreeAllAllocations( wdmHostApi->allocations );
-        PaUtil_DestroyAllocationGroup( wdmHostApi->allocations );
-    }
-    PaUtil_FreeMemory( wdmHostApi );
-    PA_LOGL_;
-}
-
-static void FillWFEXT( WAVEFORMATEXTENSIBLE* pwfext, PaSampleFormat sampleFormat, double sampleRate, int channelCount)
-{
-    PA_LOGE_;
-    PA_DEBUG(( "sampleFormat = %lx\n" , sampleFormat ));
-    PA_DEBUG(( "sampleRate = %f\n" , sampleRate ));
-    PA_DEBUG(( "chanelCount = %d\n", channelCount ));
-
-    pwfext->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
-    pwfext->Format.nChannels = channelCount;
-    pwfext->Format.nSamplesPerSec = (int)sampleRate;
-    if(channelCount == 1)
-        pwfext->dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT;
-    else
-        pwfext->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
-    if(sampleFormat == paFloat32)
-    {
-        pwfext->Format.nBlockAlign = channelCount * 4;
-        pwfext->Format.wBitsPerSample = 32;
-        pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
-        pwfext->Samples.wValidBitsPerSample = 32;
-        pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
-    }
-    else if(sampleFormat == paInt32)
-    {
-        pwfext->Format.nBlockAlign = channelCount * 4;
-        pwfext->Format.wBitsPerSample = 32;
-        pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
-        pwfext->Samples.wValidBitsPerSample = 32;
-        pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-    }
-    else if(sampleFormat == paInt24)
-    {
-        pwfext->Format.nBlockAlign = channelCount * 3;
-        pwfext->Format.wBitsPerSample = 24;
-        pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
-        pwfext->Samples.wValidBitsPerSample = 24;
-        pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-    }
-    else if(sampleFormat == paInt16)
-    {
-        pwfext->Format.nBlockAlign = channelCount * 2;
-        pwfext->Format.wBitsPerSample = 16;
-        pwfext->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
-        pwfext->Samples.wValidBitsPerSample = 16;
-        pwfext->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-    }
-    pwfext->Format.nAvgBytesPerSec = pwfext->Format.nSamplesPerSec * pwfext->Format.nBlockAlign;
-
-    PA_LOGL_;
-}
-
-static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
-                                  const PaStreamParameters *inputParameters,
-                                  const PaStreamParameters *outputParameters,
-                                  double sampleRate )
-{
-    int inputChannelCount, outputChannelCount;
-    PaSampleFormat inputSampleFormat, outputSampleFormat;
-    PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
-    PaWinWdmFilter* pFilter;
-    int result = paFormatIsSupported;
-    WAVEFORMATEXTENSIBLE wfx;
-
-    PA_LOGE_;
-
-    if( inputParameters )
-    {
-        inputChannelCount = inputParameters->channelCount;
-        inputSampleFormat = inputParameters->sampleFormat;
-
-        /* all standard sample formats are supported by the buffer adapter,
-            this implementation doesn't support any custom sample formats */
-        if( inputSampleFormat & paCustomFormat )
-            return paSampleFormatNotSupported;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that input device can support inputChannelCount */
-        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
-            return paInvalidChannelCount;
-
-        /* validate inputStreamInfo */
-        if( inputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-
-        /* Check that the input format is supported */
-        FillWFEXT(&wfx,paInt16,sampleRate,inputChannelCount);
-
-        pFilter = wdmHostApi->filters[inputParameters->device];
-        result = FilterCanCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx);
-        if( result != paNoError )
-        {
-            /* Try a WAVE_FORMAT_PCM instead */
-            wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
-            wfx.Format.cbSize = 0;
-            wfx.Samples.wValidBitsPerSample = 0;
-            wfx.dwChannelMask = 0;
-            wfx.SubFormat = GUID_NULL;
-            result = FilterCanCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx);
-            if( result != paNoError )
-                 return result;
-        }
-    }
-    else
-    {
-        inputChannelCount = 0;
-    }
-
-    if( outputParameters )
-    {
-        outputChannelCount = outputParameters->channelCount;
-        outputSampleFormat = outputParameters->sampleFormat;
-
-        /* all standard sample formats are supported by the buffer adapter,
-            this implementation doesn't support any custom sample formats */
-        if( outputSampleFormat & paCustomFormat )
-            return paSampleFormatNotSupported;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that output device can support outputChannelCount */
-        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
-            return paInvalidChannelCount;
-
-        /* validate outputStreamInfo */
-        if( outputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-
-        /* Check that the output format is supported */
-        FillWFEXT(&wfx,paInt16,sampleRate,outputChannelCount);
-
-        pFilter = wdmHostApi->filters[outputParameters->device];
-        result = FilterCanCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx);
-        if( result != paNoError )
-        {
-            /* Try a WAVE_FORMAT_PCM instead */
-            wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
-            wfx.Format.cbSize = 0;
-            wfx.Samples.wValidBitsPerSample = 0;
-            wfx.dwChannelMask = 0;
-            wfx.SubFormat = GUID_NULL;
-            result = FilterCanCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx);
-            if( result != paNoError )
-                 return result;
-        }
-
-    }
-    else
-    {
-        outputChannelCount = 0;
-    }
-
-    /*
-        IMPLEMENT ME:
-
-            - if a full duplex stream is requested, check that the combination
-                of input and output parameters is supported if necessary
-
-            - check that the device supports sampleRate
-
-        Because the buffer adapter handles conversion between all standard
-        sample formats, the following checks are only required if paCustomFormat
-        is implemented, or under some other unusual conditions.
-
-            - check that input device can support inputSampleFormat, or that
-                we have the capability to convert from inputSampleFormat to
-                a native format
-
-            - check that output device can support outputSampleFormat, or that
-                we have the capability to convert from outputSampleFormat to
-                a native format
-    */
-    if((inputChannelCount == 0)&&(outputChannelCount == 0))
-            result = paSampleFormatNotSupported; /* Not right error */
-
-    PA_LOGL_;
-    return result;
-}
-
-/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
-
-static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
-                           PaStream** s,
-                           const PaStreamParameters *inputParameters,
-                           const PaStreamParameters *outputParameters,
-                           double sampleRate,
-                           unsigned long framesPerBuffer,
-                           PaStreamFlags streamFlags,
-                           PaStreamCallback *streamCallback,
-                           void *userData )
-{
-    PaError result = paNoError;
-    PaWinWdmHostApiRepresentation *wdmHostApi = (PaWinWdmHostApiRepresentation*)hostApi;
-    PaWinWdmStream *stream = 0;
-    /* unsigned long framesPerHostBuffer; these may not be equivalent for all implementations */
-    PaSampleFormat inputSampleFormat, outputSampleFormat;
-    PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
-    int userInputChannels,userOutputChannels;
-    int size;
-    PaWinWdmFilter* pFilter;
-    WAVEFORMATEXTENSIBLE wfx;
-
-    PA_LOGE_;
-    PA_DEBUG(("OpenStream:sampleRate = %f\n",sampleRate));
-    PA_DEBUG(("OpenStream:framesPerBuffer = %lu\n",framesPerBuffer));
-
-    if( inputParameters )
-    {
-        userInputChannels = inputParameters->channelCount;
-        inputSampleFormat = inputParameters->sampleFormat;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that input device can support stream->userInputChannels */
-        if( userInputChannels > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
-            return paInvalidChannelCount;
-
-        /* validate inputStreamInfo */
-        if( inputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-
-    }
-    else
-    {
-        userInputChannels = 0;
-        inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
-    }
-
-    if( outputParameters )
-    {
-        userOutputChannels = outputParameters->channelCount;
-        outputSampleFormat = outputParameters->sampleFormat;
-
-        /* unless alternate device specification is supported, reject the use of
-            paUseHostApiSpecificDeviceSpecification */
-
-        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
-            return paInvalidDevice;
-
-        /* check that output device can support stream->userInputChannels */
-        if( userOutputChannels > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
-            return paInvalidChannelCount;
-
-        /* validate outputStreamInfo */
-        if( outputParameters->hostApiSpecificStreamInfo )
-            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
-
-    }
-    else
-    {
-        userOutputChannels = 0;
-        outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
-    }
-
-    /* validate platform specific flags */
-    if( (streamFlags & paPlatformSpecificFlags) != 0 )
-        return paInvalidFlag; /* unexpected platform specific flag */
-
-    stream = (PaWinWdmStream*)PaUtil_AllocateMemory( sizeof(PaWinWdmStream) );
-    if( !stream )
-    {
-        result = paInsufficientMemory;
-        goto error;
-    }
-    /* Zero the stream object */
-    /* memset((void*)stream,0,sizeof(PaWinWdmStream)); */
-
-    if( streamCallback )
-    {
-        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
-                                               &wdmHostApi->callbackStreamInterface, streamCallback, userData );
-    }
-    else
-    {
-        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
-                                               &wdmHostApi->blockingStreamInterface, streamCallback, userData );
-    }
-
-    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
-
-    /* Instantiate the input pin if necessary */
-    if(userInputChannels > 0)
-    {
-        result = paSampleFormatNotSupported;
-        pFilter = wdmHostApi->filters[inputParameters->device];
-        stream->userInputChannels = userInputChannels;
-
-        if(((inputSampleFormat & ~paNonInterleaved) & pFilter->formats) != 0)
-        {   /* inputSampleFormat is supported, so try to use it */
-            hostInputSampleFormat = inputSampleFormat;
-            FillWFEXT(&wfx, hostInputSampleFormat, sampleRate, stream->userInputChannels);
-            stream->bytesPerInputFrame = wfx.Format.nBlockAlign;
-            stream->recordingPin = FilterCreateCapturePin(pFilter, (const WAVEFORMATEX*)&wfx, &result);
-            stream->deviceInputChannels = stream->userInputChannels;
-        }
-        
-        if(result != paNoError)
-        {   /* Search through all PaSampleFormats to find one that works */
-            hostInputSampleFormat = paFloat32;
-
-            do {
-                FillWFEXT(&wfx, hostInputSampleFormat, sampleRate, stream->userInputChannels);
-                stream->bytesPerInputFrame = wfx.Format.nBlockAlign;
-                stream->recordingPin = FilterCreateCapturePin(pFilter, (const WAVEFORMATEX*)&wfx, &result);
-                stream->deviceInputChannels = stream->userInputChannels;
-                
-                if(stream->recordingPin == NULL) result = paSampleFormatNotSupported;
-                if(result != paNoError)    hostInputSampleFormat <<= 1;
-            }
-            while(result != paNoError && hostInputSampleFormat <= paUInt8);
-        }
-
-        if(result != paNoError)
-        {    /* None of the PaSampleFormats worked.  Set the hostInputSampleFormat to the best fit
-             * and try a PCM format.
-             **/
-            hostInputSampleFormat =
-                PaUtil_SelectClosestAvailableFormat( pFilter->formats, inputSampleFormat );
-
-            /* Try a WAVE_FORMAT_PCM instead */
-            wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
-            wfx.Format.cbSize = 0;
-            wfx.Samples.wValidBitsPerSample = 0;
-            wfx.dwChannelMask = 0;
-            wfx.SubFormat = GUID_NULL;
-            stream->recordingPin = FilterCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx,&result);
-            if(stream->recordingPin == NULL) result = paSampleFormatNotSupported;
-        }
-
-        if( result != paNoError )
-        {
-            /* Some or all KS devices can only handle the exact number of channels
-             * they specify. But PortAudio clients expect to be able to
-             * at least specify mono I/O on a multi-channel device
-             * If this is the case, then we will do the channel mapping internally
-             **/
-            if( stream->userInputChannels < pFilter->maxInputChannels )
-            {
-                FillWFEXT(&wfx,hostInputSampleFormat,sampleRate,pFilter->maxInputChannels);
-                stream->bytesPerInputFrame = wfx.Format.nBlockAlign;
-                stream->recordingPin = FilterCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx,&result);
-                stream->deviceInputChannels = pFilter->maxInputChannels;
-
-                if( result != paNoError )
-                {
-                    /* Try a WAVE_FORMAT_PCM instead */
-                    wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
-                    wfx.Format.cbSize = 0;
-                    wfx.Samples.wValidBitsPerSample = 0;
-                    wfx.dwChannelMask = 0;
-                    wfx.SubFormat = GUID_NULL;
-                    stream->recordingPin = FilterCreateCapturePin(pFilter,(const WAVEFORMATEX*)&wfx,&result);
-                }
-            }
-        }
-
-        if(stream->recordingPin == NULL)
-        {
-            goto error;
-        }
-
-        switch(hostInputSampleFormat)
-        {
-            case paInt16: stream->inputSampleSize = 2; break;
-            case paInt24: stream->inputSampleSize = 3; break;
-            case paInt32:
-            case paFloat32:    stream->inputSampleSize = 4; break;
-        }
-
-        stream->recordingPin->frameSize /= stream->bytesPerInputFrame;
-        PA_DEBUG(("Pin output frames: %d\n",stream->recordingPin->frameSize));
-    }
-    else
-    {
-        stream->recordingPin = NULL;
-        stream->bytesPerInputFrame = 0;
-    }
-
-    /* Instantiate the output pin if necessary */
-    if(userOutputChannels > 0)
-    {
-        result = paSampleFormatNotSupported;
-        pFilter = wdmHostApi->filters[outputParameters->device];
-        stream->userOutputChannels = userOutputChannels;
-
-        if(((outputSampleFormat & ~paNonInterleaved) & pFilter->formats) != 0)
-        {
-            hostOutputSampleFormat = outputSampleFormat;
-            FillWFEXT(&wfx,hostOutputSampleFormat,sampleRate,stream->userOutputChannels);
-            stream->bytesPerOutputFrame = wfx.Format.nBlockAlign;
-            stream->playbackPin = FilterCreateRenderPin(pFilter,(WAVEFORMATEX*)&wfx,&result);
-            stream->deviceOutputChannels = stream->userOutputChannels;
-        }
-
-        if(result != paNoError)
-        {
-            hostOutputSampleFormat = paFloat32;
-
-            do {
-                FillWFEXT(&wfx,hostOutputSampleFormat,sampleRate,stream->userOutputChannels);
-                stream->bytesPerOutputFrame = wfx.Format.nBlockAlign;
-                stream->playbackPin = FilterCreateRenderPin(pFilter,(WAVEFORMATEX*)&wfx,&result);
-                stream->deviceOutputChannels = stream->userOutputChannels;
-
-                if(stream->playbackPin == NULL) result = paSampleFormatNotSupported;
-                if(result != paNoError)    hostOutputSampleFormat <<= 1;
-            }
-            while(result != paNoError && hostOutputSampleFormat <= paUInt8);
-        }
-
-        if(result != paNoError)
-        {
-            hostOutputSampleFormat =
-                PaUtil_SelectClosestAvailableFormat( pFilter->formats, outputSampleFormat );
-       
-            /* Try a WAVE_FORMAT_PCM instead */
-            wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
-            wfx.Format.cbSize = 0;
-            wfx.Samples.wValidBitsPerSample = 0;
-            wfx.dwChannelMask = 0;
-            wfx.SubFormat = GUID_NULL;
-            stream->playbackPin = FilterCreateRenderPin(pFilter,(WAVEFORMATEX*)&wfx,&result);
-            if(stream->playbackPin == NULL) result = paSampleFormatNotSupported;
-        }
-            
-        if( result != paNoError )
-        {
-            /* Some or all KS devices can only handle the exact number of channels
-             * they specify. But PortAudio clients expect to be able to
-             * at least specify mono I/O on a multi-channel device
-             * If this is the case, then we will do the channel mapping internally
-             **/
-            if( stream->userOutputChannels < pFilter->maxOutputChannels )
-            {
-                FillWFEXT(&wfx,hostOutputSampleFormat,sampleRate,pFilter->maxOutputChannels);
-                stream->bytesPerOutputFrame = wfx.Format.nBlockAlign;
-                stream->playbackPin = FilterCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx,&result);
-                stream->deviceOutputChannels = pFilter->maxOutputChannels;
-                if( result != paNoError )
-                {
-                    /* Try a WAVE_FORMAT_PCM instead */
-                    wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
-                    wfx.Format.cbSize = 0;
-                    wfx.Samples.wValidBitsPerSample = 0;
-                    wfx.dwChannelMask = 0;
-                    wfx.SubFormat = GUID_NULL;
-                    stream->playbackPin = FilterCreateRenderPin(pFilter,(const WAVEFORMATEX*)&wfx,&result);
-                }
-            }
-        }
-
-        if(stream->playbackPin == NULL)
-        {
-            goto error;
-        }
-
-        switch(hostOutputSampleFormat)
-        {
-            case paInt16: stream->outputSampleSize = 2; break;
-            case paInt24: stream->outputSampleSize = 3; break;
-            case paInt32:
-            case paFloat32: stream->outputSampleSize = 4; break;
-        }
-
-        stream->playbackPin->frameSize /= stream->bytesPerOutputFrame;
-        PA_DEBUG(("Pin output frames: %d\n",stream->playbackPin->frameSize));
-    }
-    else
-    {
-        stream->playbackPin = NULL;
-        stream->bytesPerOutputFrame = 0;
-    }
-
-    /* Calculate the framesPerHostXxxxBuffer size based upon the suggested latency values */
-
-    /* Record the buffer length */
-    if(inputParameters)
-    {
-        /* Calculate the frames from the user's value - add a bit to round up */
-            stream->framesPerHostIBuffer = (unsigned long)((inputParameters->suggestedLatency*sampleRate)+0.0001);
-        if(stream->framesPerHostIBuffer > (unsigned long)sampleRate)
-        { /* Upper limit is 1 second */
-              stream->framesPerHostIBuffer = (unsigned long)sampleRate;
-        }
-        else if(stream->framesPerHostIBuffer < stream->recordingPin->frameSize)
-        {
-              stream->framesPerHostIBuffer = stream->recordingPin->frameSize;
-        }
-        PA_DEBUG(("Input frames chosen:%ld\n",stream->framesPerHostIBuffer));
-    }
-
-    if(outputParameters)
-    {
-        /* Calculate the frames from the user's value - add a bit to round up */
-        stream->framesPerHostOBuffer = (unsigned long)((outputParameters->suggestedLatency*sampleRate)+0.0001);
-        if(stream->framesPerHostOBuffer > (unsigned long)sampleRate)
-        { /* Upper limit is 1 second */
-                  stream->framesPerHostOBuffer = (unsigned long)sampleRate;
-        }
-        else if(stream->framesPerHostOBuffer < stream->playbackPin->frameSize)
-        {
-              stream->framesPerHostOBuffer = stream->playbackPin->frameSize;
-        }
-        PA_DEBUG(("Output frames chosen:%ld\n",stream->framesPerHostOBuffer));
-    }
-
-    /* Host buffer size is bounded to the largest of the input and output
-    frame sizes */
-
-    result =  PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
-              stream->userInputChannels, inputSampleFormat, hostInputSampleFormat,
-              stream->userOutputChannels, outputSampleFormat, hostOutputSampleFormat,
-              sampleRate, streamFlags, framesPerBuffer,
-              max(stream->framesPerHostOBuffer,stream->framesPerHostIBuffer),
-              paUtilBoundedHostBufferSize,
-              streamCallback, userData );
-    if( result != paNoError )
-        goto error;
-
-    stream->streamRepresentation.streamInfo.inputLatency =
-            ((double)stream->framesPerHostIBuffer) / sampleRate;
-    stream->streamRepresentation.streamInfo.outputLatency =
-            ((double)stream->framesPerHostOBuffer) / sampleRate;
-    stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
-
-      PA_DEBUG(("BytesPerInputFrame = %d\n",stream->bytesPerInputFrame));
-      PA_DEBUG(("BytesPerOutputFrame = %d\n",stream->bytesPerOutputFrame));
-
-    /* Allocate all the buffers for host I/O */
-    size = 2 * (stream->framesPerHostIBuffer*stream->bytesPerInputFrame +  stream->framesPerHostOBuffer*stream->bytesPerOutputFrame);
-    PA_DEBUG(("Buffer size = %d\n",size));
-    stream->hostBuffer = (char*)PaUtil_AllocateMemory(size);
-    PA_DEBUG(("Buffer allocated\n"));
-    if( !stream->hostBuffer )
-    {
-        PA_DEBUG(("Cannot allocate host buffer!\n"));
-        result = paInsufficientMemory;
-        goto error;
-    }
-    PA_DEBUG(("Buffer start = %p\n",stream->hostBuffer));
-    /* memset(stream->hostBuffer,0,size); */
-
-    /* Set up the packets */
-    stream->events[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
-    ResetEvent(stream->events[0]); /* Record buffer 1 */
-    stream->events[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
-    ResetEvent(stream->events[1]); /* Record buffer 2 */
-    stream->events[2] = CreateEvent(NULL, FALSE, FALSE, NULL);
-    ResetEvent(stream->events[2]); /* Play buffer 1 */
-    stream->events[3] = CreateEvent(NULL, FALSE, FALSE, NULL);
-    ResetEvent(stream->events[3]); /* Play buffer 2 */
-    stream->events[4] = CreateEvent(NULL, FALSE, FALSE, NULL);
-    ResetEvent(stream->events[4]); /* Abort event */
-    if(stream->userInputChannels > 0)
-    {
-        DATAPACKET *p = &(stream->packets[0]);
-        p->Signal.hEvent = stream->events[0];
-        p->Header.Data = stream->hostBuffer;
-        p->Header.FrameExtent = stream->framesPerHostIBuffer*stream->bytesPerInputFrame;
-        p->Header.DataUsed = 0;
-        p->Header.Size = sizeof(p->Header);
-        p->Header.PresentationTime.Numerator = 1;
-        p->Header.PresentationTime.Denominator = 1;
-
-        p = &(stream->packets[1]);
-        p->Signal.hEvent = stream->events[1];
-        p->Header.Data = stream->hostBuffer + stream->framesPerHostIBuffer*stream->bytesPerInputFrame;
-        p->Header.FrameExtent = stream->framesPerHostIBuffer*stream->bytesPerInputFrame;
-        p->Header.DataUsed = 0;
-        p->Header.Size = sizeof(p->Header);
-        p->Header.PresentationTime.Numerator = 1;
-        p->Header.PresentationTime.Denominator = 1;
-    }
-    if(stream->userOutputChannels > 0)
-    {
-        DATAPACKET *p = &(stream->packets[2]);
-        p->Signal.hEvent = stream->events[2];
-        p->Header.Data = stream->hostBuffer + 2*stream->framesPerHostIBuffer*stream->bytesPerInputFrame;
-        p->Header.FrameExtent = stream->framesPerHostOBuffer*stream->bytesPerOutputFrame;
-        p->Header.DataUsed = stream->framesPerHostOBuffer*stream->bytesPerOutputFrame;
-        p->Header.Size = sizeof(p->Header);
-        p->Header.PresentationTime.Numerator = 1;
-        p->Header.PresentationTime.Denominator = 1;
-    
-        p = &(stream->packets[3]);
-        p->Signal.hEvent = stream->events[3];
-        p->Header.Data = stream->hostBuffer + 2*stream->framesPerHostIBuffer*stream->bytesPerInputFrame + stream->framesPerHostOBuffer*stream->bytesPerOutputFrame;
-        p->Header.FrameExtent = stream->framesPerHostOBuffer*stream->bytesPerOutputFrame;
-        p->Header.DataUsed = stream->framesPerHostOBuffer*stream->bytesPerOutputFrame;
-        p->Header.Size = sizeof(p->Header);
-        p->Header.PresentationTime.Numerator = 1;
-        p->Header.PresentationTime.Denominator = 1;
-    }
-
-    stream->streamStarted = 0;
-    stream->streamActive = 0;
-    stream->streamStop = 0;
-    stream->streamAbort = 0;
-    stream->streamFlags = streamFlags;
-    stream->oldProcessPriority = REALTIME_PRIORITY_CLASS;
-
-    *s = (PaStream*)stream;
-
-    PA_LOGL_;
-    return result;
-
-error:
-    size = 5;
-    while(size--)
-    {
-        if(stream->events[size] != NULL)
-        {
-            CloseHandle(stream->events[size]);
-            stream->events[size] = NULL;
-        }
-    }
-    if(stream->hostBuffer)
-        PaUtil_FreeMemory( stream->hostBuffer );
-
-    if(stream->playbackPin)
-        PinClose(stream->playbackPin);
-    if(stream->recordingPin)
-        PinClose(stream->recordingPin);
-
-    if( stream )
-        PaUtil_FreeMemory( stream );
-
-    PA_LOGL_;
-    return result;
-}
-
-/*
-    When CloseStream() is called, the multi-api layer ensures that
-    the stream has already been stopped or aborted.
-*/
-static PaError CloseStream( PaStream* s )
-{
-    PaError result = paNoError;
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-    int size;
-
-    PA_LOGE_;
-
-    assert(!stream->streamStarted);
-    assert(!stream->streamActive);
-
-    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
-    PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
-    size = 5;
-    while(size--)
-    {
-        if(stream->events[size] != NULL)
-        {
-            CloseHandle(stream->events[size]);
-            stream->events[size] = NULL;
-        }
-    }
-    if(stream->hostBuffer)
-        PaUtil_FreeMemory( stream->hostBuffer );
-
-    if(stream->playbackPin)
-        PinClose(stream->playbackPin);
-    if(stream->recordingPin)
-        PinClose(stream->recordingPin);
-
-    PaUtil_FreeMemory( stream );
-
-    PA_LOGL_;
-    return result;
-}
-
-/*
-Write the supplied packet to the pin
-Asynchronous
-Should return false on success
-*/
-static BOOL PinWrite(HANDLE h, DATAPACKET* p)
-{
-    unsigned long cbReturned = 0;
-    return DeviceIoControl(h,IOCTL_KS_WRITE_STREAM,NULL,0,
-                            &p->Header,p->Header.Size,&cbReturned,&p->Signal);
-}
-
-/*
-Read to the supplied packet from the pin
-Asynchronous
-Should return false on success
-*/
-static BOOL PinRead(HANDLE h, DATAPACKET* p)
-{
-    unsigned long cbReturned = 0;
-    return DeviceIoControl(h,IOCTL_KS_READ_STREAM,NULL,0,
-                            &p->Header,p->Header.Size,&cbReturned,&p->Signal);
-}
-
-/*
-Copy the first interleaved channel of 16 bit data to the other channels
-*/
-static void DuplicateFirstChannelInt16(void* buffer, int channels, int samples)
-{
-    unsigned short* data = (unsigned short*)buffer;
-    int channel;
-    unsigned short sourceSample;
-    while( samples-- )
-    {
-        sourceSample = *data++;
-        channel = channels-1;
-        while( channel-- )
-        {
-            *data++ = sourceSample;
-        }
-    }
-}
-
-/*
-Copy the first interleaved channel of 24 bit data to the other channels
-*/
-static void DuplicateFirstChannelInt24(void* buffer, int channels, int samples)
-{
-    unsigned char* data = (unsigned char*)buffer;
-    int channel;
-    unsigned char sourceSample[3];
-    while( samples-- )
-    {
-        sourceSample[0] = data[0];
-        sourceSample[1] = data[1];
-        sourceSample[2] = data[2];
-        data += 3;
-        channel = channels-1;
-        while( channel-- )
-        {
-            data[0] = sourceSample[0];
-            data[1] = sourceSample[1];
-            data[2] = sourceSample[2];
-            data += 3;
-        }
-    }
-}
-
-/*
-Copy the first interleaved channel of 32 bit data to the other channels
-*/
-static void DuplicateFirstChannelInt32(void* buffer, int channels, int samples)
-{
-    unsigned long* data = (unsigned long*)buffer;
-    int channel;
-    unsigned long sourceSample;
-    while( samples-- )
-    {
-        sourceSample = *data++;
-        channel = channels-1;
-        while( channel-- )
-        {
-            *data++ = sourceSample;
-        }
-    }
-}
-
-static DWORD WINAPI ProcessingThread(LPVOID pParam)
-{
-    PaWinWdmStream *stream = (PaWinWdmStream*)pParam;
-    PaStreamCallbackTimeInfo ti;
-    int cbResult = paContinue;
-    int inbuf = 0;
-    int outbuf = 0;
-    int pending = 0;
-    PaError result;
-    unsigned long wait;
-    unsigned long eventSignaled;
-    int fillPlaybuf = 0;
-    int emptyRecordbuf = 0;
-    int framesProcessed;
-    unsigned long timeout;
-    int i;
-    int doChannelCopy;
-    int priming = 0;
-    PaStreamCallbackFlags underover = 0;
-
-    PA_LOGE_;
-
-    ti.inputBufferAdcTime = 0.0;
-    ti.currentTime = 0.0;
-    ti.outputBufferDacTime = 0.0;
-
-    /* Get double buffering going */
-
-    /* Submit buffers */
-    if(stream->playbackPin)
-    {
-        result = PinSetState(stream->playbackPin, KSSTATE_RUN);
-
-        PA_DEBUG(("play state run = %d;",(int)result));
-        SetEvent(stream->events[outbuf+2]);
-        outbuf = (outbuf+1)&1;
-        SetEvent(stream->events[outbuf+2]);
-        outbuf = (outbuf+1)&1;
-        pending += 2;
-        priming += 4;
-    }
-    if(stream->recordingPin)
-    {
-        result = PinSetState(stream->recordingPin, KSSTATE_RUN);
-
-        PA_DEBUG(("recording state run = %d;",(int)result));
-        PinRead(stream->recordingPin->handle,&stream->packets[inbuf]);
-        inbuf = (inbuf+1)&1; /* Increment and wrap */
-        PinRead(stream->recordingPin->handle,&stream->packets[inbuf]);
-        inbuf = (inbuf+1)&1; /* Increment and wrap */
-        /* FIXME - do error checking */
-        pending += 2;
-    }
-    PA_DEBUG(("Out buffer len:%f\n",(2000*stream->framesPerHostOBuffer) / stream->streamRepresentation.streamInfo.sampleRate));
-    PA_DEBUG(("In buffer len:%f\n",(2000*stream->framesPerHostIBuffer) / stream->streamRepresentation.streamInfo.sampleRate));
-    timeout = max(
-       ((2000*(DWORD)stream->framesPerHostOBuffer) / (DWORD)stream->streamRepresentation.streamInfo.sampleRate),
-       ((2000*(DWORD)stream->framesPerHostIBuffer) / (DWORD)stream->streamRepresentation.streamInfo.sampleRate));
-    timeout = max(timeout,1);
-    PA_DEBUG(("Timeout = %ld\n",timeout));
-
-    while(!stream->streamAbort)
-    {
-        fillPlaybuf = 0;
-        emptyRecordbuf = 0;
-
-        /* Wait for next input or output buffer to be finished with*/
-        assert(pending>0);
-
-        if(stream->streamStop)
-        {
-            PA_DEBUG(("ss1:pending=%d ",pending));
-        }
-        wait = WaitForMultipleObjects(5, stream->events, FALSE, 0);
-        if( wait == WAIT_TIMEOUT )
-        {
-            /* No (under|over)flow has ocurred */
-            wait = WaitForMultipleObjects(5, stream->events, FALSE, timeout);
-            eventSignaled = wait - WAIT_OBJECT_0;
-        }
-        else
-        {
-            eventSignaled = wait - WAIT_OBJECT_0;
-            if( eventSignaled < 2 )
-            {
-                underover |= paInputOverflow;
-                PA_DEBUG(("Input overflow\n"));
-            }
-            else if(( eventSignaled < 4 )&&(!priming))
-            {
-                underover |= paOutputUnderflow;
-                PA_DEBUG(("Output underflow\n"));
-            }
-        }
-
-        if(stream->streamStop)
-        {
-            PA_DEBUG(("ss2:wait=%ld",wait));
-        }
-        if(wait == WAIT_FAILED)
-        {
-            PA_DEBUG(("Wait fail = %ld! ",wait));
-            break;
-        }
-        if(wait == WAIT_TIMEOUT)
-        {
-            continue;
-        }
-
-        if(eventSignaled < 2)
-        { /* Recording input buffer has been filled */
-            if(stream->playbackPin)
-            {
-                /* First check if also the next playback buffer has been signaled */
-                wait = WaitForSingleObject(stream->events[outbuf+2],0);
-                if(wait == WAIT_OBJECT_0)
-                {
-                    /* Yes, so do both buffers at same time */
-                    fillPlaybuf = 1;
-                    pending--;
-                    /* Was this an underflow situation? */
-                    if( underover )
-                        underover |= paOutputUnderflow; /* Yes! */
-                }
-            }
-            emptyRecordbuf = 1;
-            pending--;
-        }
-        else if(eventSignaled < 4)
-        { /* Playback output buffer has been emptied */
-            if(stream->recordingPin)
-            {
-                /* First check if also the next recording buffer has been signaled */
-                wait = WaitForSingleObject(stream->events[inbuf],0);
-                if(wait == WAIT_OBJECT_0)
-                { /* Yes, so do both buffers at same time */
-                    emptyRecordbuf = 1;
-                    pending--;
-                    /* Was this an overflow situation? */
-                    if( underover )
-                        underover |= paInputOverflow; /* Yes! */
-                }
-            }
-            fillPlaybuf = 1;
-            pending--;
-        }
-        else
-        {
-            /* Abort event! */
-            assert(stream->streamAbort); /* Should have been set */
-            PA_DEBUG(("ABORTING "));
-            break;
-        }
-        ResetEvent(stream->events[eventSignaled]);
-
-        if(stream->streamStop)
-        {
-            PA_DEBUG(("Stream stop! pending=%d",pending));
-            cbResult = paComplete; /* Stop, but play remaining buffers */
-        }
-
-        /* Do necessary buffer processing (which will invoke user callback if necessary */
-        doChannelCopy = 0;
-        if(cbResult==paContinue)
-        {
-            PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
-            if((stream->bufferProcessor.hostInputFrameCount[0] + stream->bufferProcessor.hostInputFrameCount[1]) ==
-                (stream->bufferProcessor.hostOutputFrameCount[0] + stream->bufferProcessor.hostOutputFrameCount[1]) )
-                PaUtil_BeginBufferProcessing(&stream->bufferProcessor,&ti,underover);
-            underover = 0; /* Reset the (under|over)flow status */
-            if(fillPlaybuf)
-            {
-                PaUtil_SetOutputFrameCount(&stream->bufferProcessor,0);
-                if( stream->userOutputChannels == 1 )
-                {
-                    /* Write the single user channel to the first interleaved block */
-                    PaUtil_SetOutputChannel(&stream->bufferProcessor,0,stream->packets[outbuf+2].Header.Data,stream->deviceOutputChannels);
-                    /* We will do a copy to the other channels after the data has been written */
-                    doChannelCopy = 1;
-                }
-                else
-                {
-                    for(i=0;i<stream->userOutputChannels;i++)
-                    {
-                        /* Only write the user output channels. Leave the rest blank */
-                        PaUtil_SetOutputChannel(&stream->bufferProcessor,i,((unsigned char*)(stream->packets[outbuf+2].Header.Data))+(i*stream->outputSampleSize),stream->deviceOutputChannels);
-                    }
-                }
-            }
-            if(emptyRecordbuf)
-            {
-                PaUtil_SetInputFrameCount(&stream->bufferProcessor,stream->packets[inbuf].Header.DataUsed/stream->bytesPerInputFrame);
-                for(i=0;i<stream->userInputChannels;i++)
-                {
-                    /* Only read as many channels as the user wants */
-                    PaUtil_SetInputChannel(&stream->bufferProcessor,i,((unsigned char*)(stream->packets[inbuf].Header.Data))+(i*stream->inputSampleSize),stream->deviceInputChannels);
-                }
-            }
-            /* Only call the EndBufferProcessing function is the total input frames == total output frames */
-            if((stream->bufferProcessor.hostInputFrameCount[0] + stream->bufferProcessor.hostInputFrameCount[1]) ==
-                (stream->bufferProcessor.hostOutputFrameCount[0] + stream->bufferProcessor.hostOutputFrameCount[1]) )
-                framesProcessed = PaUtil_EndBufferProcessing(&stream->bufferProcessor,&cbResult);
-            else framesProcessed = 0;
-            if( doChannelCopy )
-            {
-                /* Copy the first output channel to the other channels */
-                switch(stream->outputSampleSize)
-                {
-                    case 2:
-                        DuplicateFirstChannelInt16(stream->packets[outbuf+2].Header.Data,stream->deviceOutputChannels,stream->framesPerHostOBuffer);
-                        break;
-                    case 3:
-                        DuplicateFirstChannelInt24(stream->packets[outbuf+2].Header.Data,stream->deviceOutputChannels,stream->framesPerHostOBuffer);
-                        break;
-                    case 4:
-                        DuplicateFirstChannelInt32(stream->packets[outbuf+2].Header.Data,stream->deviceOutputChannels,stream->framesPerHostOBuffer);
-                        break;
-                    default:
-                        assert(0); /* Unsupported format! */
-                        break;
-                }
-            }
-            PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
-        }
-        else
-        {
-            fillPlaybuf = 0;
-            emptyRecordbuf = 0;
-        }
-            
-        /*
-        if(cbResult != paContinue)
-        {
-            PA_DEBUG(("cbResult=%d, pending=%d:",cbResult,pending));
-        }
-        */
-        /* Submit buffers */
-        if((fillPlaybuf)&&(cbResult!=paAbort))
-        {
-            if(!PinWrite(stream->playbackPin->handle,&stream->packets[outbuf+2]))
-                outbuf = (outbuf+1)&1; /* Increment and wrap */
-            pending++;
-            if( priming )
-                priming--; /* Have to prime twice */
-        }
-        if((emptyRecordbuf)&&(cbResult==paContinue))
-        {
-            stream->packets[inbuf].Header.DataUsed = 0; /* Reset for reuse */
-            PinRead(stream->recordingPin->handle,&stream->packets[inbuf]);
-            inbuf = (inbuf+1)&1; /* Increment and wrap */
-            pending++;
-        }
-        if(pending==0)
-        {
-            PA_DEBUG(("pending==0 finished...;"));
-            break;
-        }
-        if((!stream->playbackPin)&&(cbResult!=paContinue))
-        {
-            PA_DEBUG(("record only cbResult=%d...;",cbResult));
-            break;
-        }
-    }
-
-    PA_DEBUG(("Finished thread"));
-
-    /* Finished, either normally or aborted */
-    if(stream->playbackPin)
-    {
-        result = PinSetState(stream->playbackPin, KSSTATE_PAUSE);
-        result = PinSetState(stream->playbackPin, KSSTATE_STOP);
-    }
-    if(stream->recordingPin)
-    {
-        result = PinSetState(stream->recordingPin, KSSTATE_PAUSE);
-        result = PinSetState(stream->recordingPin, KSSTATE_STOP);
-    }
-
-    stream->streamActive = 0;
-
-    if((!stream->streamStop)&&(!stream->streamAbort))
-    {
-          /* Invoke the user stream finished callback */
-          /* Only do it from here if not being stopped/aborted by user */
-          if( stream->streamRepresentation.streamFinishedCallback != 0 )
-              stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
-    }
-    stream->streamStop = 0;
-    stream->streamAbort = 0;
-
-    /* Reset process priority if necessary */
-    if(stream->oldProcessPriority != REALTIME_PRIORITY_CLASS)
-    {
-        SetPriorityClass(GetCurrentProcess(),stream->oldProcessPriority);
-        stream->oldProcessPriority = REALTIME_PRIORITY_CLASS;
-    }
-
-    PA_LOGL_;
-    ExitThread(0);
-    return 0;
-}
-
-static PaError StartStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-    DWORD dwID;
-    BOOL ret;
-    int size;
-
-    PA_LOGE_;
-
-    stream->streamStop = 0;
-    stream->streamAbort = 0;
-    size = 5;
-    while(size--)
-    {
-        if(stream->events[size] != NULL)
-        {
-            ResetEvent(stream->events[size]);
-        }
-    }
-
-    PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
-
-    stream->oldProcessPriority = GetPriorityClass(GetCurrentProcess());
-    /* Uncomment the following line to enable dynamic boosting of the process
-     * priority to real time for best low latency support
-     * Disabled by default because RT processes can easily block the OS */
-    /*ret = SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
-      PA_DEBUG(("Class ret = %d;",ret));*/
-
-    stream->streamStarted = 1;
-    stream->streamThread = CreateThread(NULL, 0, ProcessingThread, stream, 0, &dwID);
-    if(stream->streamThread == NULL)
-    {
-        stream->streamStarted = 0;
-        result = paInsufficientMemory;
-        goto end;
-    }
-    ret = SetThreadPriority(stream->streamThread,THREAD_PRIORITY_TIME_CRITICAL);
-    PA_DEBUG(("Priority ret = %d;",ret));
-    /* Make the stream active */
-    stream->streamActive = 1;
-
-end:
-    PA_LOGL_;
-    return result;
-}
-
-
-static PaError StopStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-    int doCb = 0;
-
-    PA_LOGE_;
-
-    if(stream->streamActive)
-    {
-        doCb = 1;
-        stream->streamStop = 1;
-        while(stream->streamActive)
-        {
-            PA_DEBUG(("W."));
-            Sleep(10); /* Let thread sleep for 10 msec */
-        }
-    }
-
-    PA_DEBUG(("Terminating thread"));
-    if(stream->streamStarted && stream->streamThread)
-    {
-        TerminateThread(stream->streamThread,0);
-        stream->streamThread = NULL;
-    }
-
-    stream->streamStarted = 0;
-
-    if(stream->oldProcessPriority != REALTIME_PRIORITY_CLASS)
-    {
-        SetPriorityClass(GetCurrentProcess(),stream->oldProcessPriority);
-        stream->oldProcessPriority = REALTIME_PRIORITY_CLASS;
-    }
-
-    if(doCb)
-    {
-        /* Do user callback now after all state has been reset */
-        /* This means it should be safe for the called function */
-        /* to invoke e.g. StartStream */
-        if( stream->streamRepresentation.streamFinishedCallback != 0 )
-             stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
-    }
-
-    PA_LOGL_;
-    return result;
-}
-
-static PaError AbortStream( PaStream *s )
-{
-    PaError result = paNoError;
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-    int doCb = 0;
-
-    PA_LOGE_;
-
-    if(stream->streamActive)
-    {
-        doCb = 1;
-        stream->streamAbort = 1;
-        SetEvent(stream->events[4]); /* Signal immediately */
-        while(stream->streamActive)
-        {
-            Sleep(10);
-        }
-    }
-
-    if(stream->streamStarted && stream->streamThread)
-    {
-        TerminateThread(stream->streamThread,0);
-        stream->streamThread = NULL;
-    }
-
-    stream->streamStarted = 0;
-
-    if(stream->oldProcessPriority != REALTIME_PRIORITY_CLASS)
-    {
-        SetPriorityClass(GetCurrentProcess(),stream->oldProcessPriority);
-        stream->oldProcessPriority = REALTIME_PRIORITY_CLASS;
-    }
-
-    if(doCb)
-    {
-        /* Do user callback now after all state has been reset */
-        /* This means it should be safe for the called function */
-        /* to invoke e.g. StartStream */
-        if( stream->streamRepresentation.streamFinishedCallback != 0 )
-            stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
-    }
-
-    stream->streamActive = 0;
-    stream->streamStarted = 0;
-
-    PA_LOGL_;
-    return result;
-}
-
-
-static PaError IsStreamStopped( PaStream *s )
-{
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-    int result = 0;
-
-    PA_LOGE_;
-
-    if(!stream->streamStarted)
-        result = 1;
-
-    PA_LOGL_;
-    return result;
-}
-
-
-static PaError IsStreamActive( PaStream *s )
-{
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-    int result = 0;
-
-    PA_LOGE_;
-
-    if(stream->streamActive)
-        result = 1;
-
-    PA_LOGL_;
-    return result;
-}
-
-
-static PaTime GetStreamTime( PaStream* s )
-{
-    PA_LOGE_;
-    PA_LOGL_;
-    (void)s;
-    return PaUtil_GetTime();
-}
-
-
-static double GetStreamCpuLoad( PaStream* s )
-{
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-    double result;
-    PA_LOGE_;
-    result = PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
-    PA_LOGL_;
-    return result;
-}
-
-
-/*
-    As separate stream interfaces are used for blocking and callback
-    streams, the following functions can be guaranteed to only be called
-    for blocking streams.
-*/
-
-static PaError ReadStream( PaStream* s,
-                           void *buffer,
-                           unsigned long frames )
-{
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-
-    PA_LOGE_;
-
-    /* suppress unused variable warnings */
-    (void) buffer;
-    (void) frames;
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-    PA_LOGL_;
-    return paNoError;
-}
-
-
-static PaError WriteStream( PaStream* s,
-                            const void *buffer,
-                            unsigned long frames )
-{
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-
-    PA_LOGE_;
-
-    /* suppress unused variable warnings */
-    (void) buffer;
-    (void) frames;
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-    PA_LOGL_;
-    return paNoError;
-}
-
-
-static signed long GetStreamReadAvailable( PaStream* s )
-{
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-
-    PA_LOGE_;
-
-    /* suppress unused variable warnings */
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-    PA_LOGL_;
-    return 0;
-}
-
-
-static signed long GetStreamWriteAvailable( PaStream* s )
-{
-    PaWinWdmStream *stream = (PaWinWdmStream*)s;
-
-    PA_LOGE_;
-    /* suppress unused variable warnings */
-    (void) stream;
-
-    /* IMPLEMENT ME, see portaudio.h for required behavior*/
-    PA_LOGL_;
-    return 0;
-}
\ No newline at end of file
diff --git a/portaudio/unused/hostapi/wdmks/readme.txt b/portaudio/unused/hostapi/wdmks/readme.txt
deleted file mode 100644
index 1a381fe79feaad47b92a40ec1a70510af2243fd3..0000000000000000000000000000000000000000
--- a/portaudio/unused/hostapi/wdmks/readme.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-Notes about WDM-KS host API
----------------------------
-
-Status history
---------------
-10th November 2005:
-Made following changes:
- * OpenStream: Try all PaSampleFormats internally if the the chosen
-     format is not supported natively.  This fixed several problems
-     with soundcards that soundcards that did not take kindly to
-     using 24-bit 3-byte formats.
- * OpenStream: Make the minimum framesPerHostIBuffer (and framesPerHostOBuffer)
-     the default frameSize for the playback/recording pin.
- * ProcessingThread: Added a switch to only call PaUtil_EndBufferProcessing
-     if the total input frames equals the total output frames
-
-5th September 2004:
-This is the first public version of the code. It should be considered
-an alpha release with zero guarantee not to crash on any particular 
-system. So far it has only been tested in the author's development
-environment, which means a Win2k/SP2 PIII laptop with integrated 
-SoundMAX driver and USB Tascam US-428 compiled with both MinGW
-(GCC 3.3) and MSVC++6 using the MS DirectX 9 SDK.
-It has been most widely tested with the MinGW build, with most of the
-test programs (particularly paqa_devs and paqa_errs) passing.
-There are some notable failures: patest_out_underflow and both of the
-blocking I/O tests (as blocking I/O is not implemented).
-At this point the code needs to be tested with a much wider variety 
-of configurations and feedback provided from testers regarding
-both working and failing cases.
-
-What is the WDM-KS host API?
-----------------------------
-PortAudio for Windows currently has 3 functional host implementations.
-MME uses the oldest Windows audio API which does not offer good
-play/record latency. 
-DirectX improves this, but still imposes a penalty
-of 10s of milliseconds due to the system mixing of streams from
-multiple applications. 
-ASIO offers very good latency, but requires special drivers which are
-not always available for cheaper audio hardware. Also, when ASIO 
-drivers are available, they are not always so robust because they 
-bypass all of the standardised Windows device driver architecture 
-and hit the hardware their own way.
-Alternatively there are a couple of free (but closed source) ASIO 
-implementations which connect to the lower level Windows 
-"Kernel Streaming" API, but again these require special installation 
-by the user, and can be limited in functionality or difficult to use. 
-
-This is where the PortAudio "WDM-KS" host implementation comes in.
-It directly connects PortAudio to the same Kernel Streaming API which
-those ASIO bridges use. This avoids the mixing penatly of DirectX, 
-giving at least as good latency as any ASIO driver, but it has the
-advantage of working with ANY Windows audio hardware which is available
-through the normal MME/DirectX routes without the user requiring 
-any additional device drivers to be installed, and allowing all 
-device selection to be done through the normal PortAudio API.
-
-Note that in general you should only be using this host API if your 
-application has a real requirement for very low latency audio (<20ms), 
-either because you are generating sounds in real-time based upon 
-user input, or you a processing recorded audio in real time.
-
-The only thing to be aware of is that using the KS interface will
-block that device from being used by the rest of system through
-the higher level APIs, or conversely, if the system is using
-a device, the KS API will not be able to use it. MS recommend that
-you should keep the device open only when your application has focus.
-In PortAudio terms, this means having a stream Open on a WDMKS device.
-
-Usage
------
-To add the WDMKS backend to your program which is already using 
-PortAudio, you must undefine PA_NO_WDMKS from your build file,
-and include the pa_win_wdmks\pa_win_wdmks.c into your build.
-The file should compile in both C and C++.
-You will need a DirectX SDK installed on your system for the
-ks.h and ksmedia.h header files.
-You will need to link to the system "setupapi" library.
-Note that if you use MinGW, you will get more warnings from 
-the DX header files when using GCC(C), and still a few warnings
-with G++(CPP).
\ No newline at end of file
diff --git a/src/m_sched.c b/src/m_sched.c
index b69d8f60b7663bdfbd6af791f26024d24d4128f2..86b053ab9f940197321be85735b807a588389052 100644
--- a/src/m_sched.c
+++ b/src/m_sched.c
@@ -334,11 +334,17 @@ double sys_time_per_dsp_tick;
 void sched_set_using_audio(int flag)
 {
     sched_useaudio = flag;
+        post("new sched %d", sched_useaudio);
     if (flag == SCHED_AUDIO_NONE)
     {
         sched_referencerealtime = sys_getrealtime();
         sched_referencelogicaltime = clock_getlogicaltime();
     }
+	if (flag == SCHED_AUDIO_CALLBACK && sched_useaudio != SCHED_AUDIO_CALLBACK)
+		sys_quit = SYS_QUIT_RESTART;
+	if (flag != SCHED_AUDIO_CALLBACK && sched_useaudio == SCHED_AUDIO_CALLBACK)
+		post("sorry, can't turn off callbacks yet; restart Pd");  /* not right yet! */
+	
     sys_time_per_dsp_tick = (TIMEUNITPERSEC) *
         ((double)sys_schedblocksize) / sys_dacsr;
 }
@@ -434,6 +440,11 @@ static void m_pollingscheduler( void)
                 if (!(idlecount & 31))
                 {
                     static double idletime;
+					if (sched_useaudio != SCHED_AUDIO_POLL)
+					{
+						bug("m_pollingscheduler\n");
+						return;
+					}
                         /* on 32nd idle, start a clock watch;  every
                         32 ensuing idles, check it */
                     if (idlecount == 32)
@@ -532,6 +543,12 @@ int m_mainloop(void)
         if (sched_useaudio == SCHED_AUDIO_CALLBACK)
             m_callbackscheduler();
         else m_pollingscheduler();
+		if (sys_quit == SYS_QUIT_RESTART)
+		{
+			sys_quit = 0;
+            sys_close_audio();
+            sys_reopen_audio();
+		}
     }
     return (0);
 }
diff --git a/src/s_audio.c b/src/s_audio.c
index b33c85a553a0b6531101f40aeaae7f689ad002c6..a1a789d9f59cecd2fe7226e290fea7d2eb76c839 100644
--- a/src/s_audio.c
+++ b/src/s_audio.c
@@ -376,6 +376,7 @@ void sys_reopen_audio( void)
     int rate, advance, callback, outcome = 0;
     sys_get_audio_params(&naudioindev, audioindev, chindev,
         &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+	post("x 1");
     if (!naudioindev && !naudiooutdev)
     {
         sched_set_using_audio(SCHED_AUDIO_NONE);
@@ -385,6 +386,7 @@ void sys_reopen_audio( void)
     if (sys_audioapi == API_PORTAUDIO)
     {
         int blksize = (sys_blocksize ? sys_blocksize : 64);
+		post("x 2 %d", callback);
         outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0),
         (naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin,
             sys_soundout, blksize, sys_advance_samples/blksize, 
@@ -422,6 +424,7 @@ void sys_reopen_audio( void)
     else
 #endif
         post("unknown audio API specified");
+	post("x 3 %d %d", callback, outcome);
     if (outcome)    /* failed */
     {
         audio_state = 0;
@@ -729,12 +732,14 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
             noutdev++;
         }
     }
-
-    sys_close_audio();
+    
+	if (audio_callback == newcallback)
+		sys_close_audio();
     sys_set_audio_settings(nindev, newaudioindev, nindev, newaudioinchan,
         noutdev, newaudiooutdev, noutdev, newaudiooutchan,
-        newrate, newadvance, newcallback);
-    sys_reopen_audio();
+        newrate, newadvance, (newcallback >= 0 ? newcallback : 0));
+	if (audio_callback == newcallback)
+		sys_reopen_audio();
 }
 
 void sys_listdevs(void )
diff --git a/src/s_audio_pa.c b/src/s_audio_pa.c
index c89d463e65c577cb00971cfed340f22887a1c4a8..f05c41d853b1d297e08d89a825ece7b0c1fa05d6 100644
--- a/src/s_audio_pa.c
+++ b/src/s_audio_pa.c
@@ -36,8 +36,12 @@ static int pa_lowlevel_callback(const void *inputBuffer,
     int i; 
     unsigned int j;
     float *fbuf, *fp2, *fp3, *soundiop;
-
-    if (inputBuffer != NULL)
+        if (framesPerBuffer != DEFDACBLKSIZE)
+        {
+                fprintf(stderr, "ignoring buffer size %d\n", framesPerBuffer);
+                return;
+    }
+        if (inputBuffer != NULL)
     {
         fbuf = (float *)inputBuffer;
         soundiop = pa_soundin;
@@ -52,9 +56,9 @@ static int pa_lowlevel_callback(const void *inputBuffer,
     {
         fbuf = (float *)outputBuffer;
         soundiop = pa_soundout;
-        for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
-            for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_inchans)
-                *fp3 = *soundiop;
+        for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++)
+            for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_outchans)
+                *fp3 = *soundiop++;
     }
 
     return 0;
@@ -119,7 +123,7 @@ PaError pa_open_callback(double sampleRate, int inchannels, int outchannels,
               (inchannels ? &instreamparams : 0),
               (outchannels ? &outstreamparams : 0),
               sampleRate,
-              framesperbuf,
+              DEFDACBLKSIZE,
               paNoFlag,      /* portaudio will clip for us */
               pa_lowlevel_callback,
               pastream);
diff --git a/src/s_inter.c b/src/s_inter.c
index e6c69bf6ec980818f7dc10454f780fbc9c2f7dd9..9945466f1bedcfa50088c613ce2dcb6008aa06bb 100644
--- a/src/s_inter.c
+++ b/src/s_inter.c
@@ -1079,6 +1079,10 @@ int sys_startgui(const char *guidir)
                     goto foundit;
             nohomedir:
                     /* Perform the same search among system applications. */
+                strcpy(filename, 
+                    "/usr/bin/wish");
+                if (stat(filename, &statbuf) >= 0)
+                    goto foundit;
                 strcpy(filename, 
                     "/Applications/Utilities/Wish Shell.app/Contents/MacOS/Wish Shell");
                 if (stat(filename, &statbuf) >= 0)
diff --git a/src/s_stuff.h b/src/s_stuff.h
index c4c26928ea6c93270f7ee6d65d22388818761714..9abd5cd356ecc4390e977b5155bbd1309531f2c2 100644
--- a/src/s_stuff.h
+++ b/src/s_stuff.h
@@ -209,7 +209,7 @@ void sys_setvirtualalarm( void);
 #define DEFAULTADVANCE 50
 #endif
 
-typedef void (*t_audiocallback)(vid);
+typedef void (*t_audiocallback)(void);
 
 int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
     t_sample *soundout, int framesperbuf, int nbuffers,
diff --git a/src/t_tkcmd.c b/src/t_tkcmd.c
index 61e66691c851aabd5fe0473d217b01e2a0852751..c32dc346be34f0d4a0ca476ec29ea564c52abdfb 100644
--- a/src/t_tkcmd.c
+++ b/src/t_tkcmd.c
@@ -619,19 +619,11 @@ int Pdtcl_Init(Tcl_Interp *interp)
 {
     const char *argv = Tcl_GetVar(interp, "argv", 0);
     int portno, argno = 0;
-        /* argument passing seems to be different in MSW as opposed to
-        unix-likes.  Here we check if we got sent a "port number" as an
-        argument.  If so. we're to connect to a previously running pd (i.e.,
-        pd got started first).  If not, we start Pd from here. */
-#ifdef MSW
     if (argv && (portno = atoi(argv)) > 1)
-#else
-    char *firstspace;
-    if (argv && (firstspace = strchr(argv, ' ')) && (portno = atoi(firstspace)) > 1)
-#endif
         pdgui_setsock(portno);
 #ifdef DEBUGCONNECT
-    debugfd = fopen("/Users/msp/bratwurst", "w");
+        pd_portno = portno;
+    debugfd = fopen("/tmp/bratwurst", "w");
     fprintf(debugfd, "turning stderr back on\n");
     fflush(debugfd);
     dup2(fileno(debugfd), 2);