Various changes in preparation for release 4.0.8
authorGary Scavone <gary@music.mcgill.ca>
Thu, 17 Feb 2011 21:26:23 +0000 (21:26 +0000)
committerStephen Sinclair <sinclair@music.mcgill.ca>
Thu, 10 Oct 2013 23:38:27 +0000 (01:38 +0200)
including fix of MinGW ASIO compile problem (iasiothiscallresolver),
OS-X problem handling device names in some languages (CFString
conversion), small change to OS-X MUTEX lock location to avoid
lockups, and correction to documentation regarding 24-bit data (should
be lower 3 bytes, not upper 3 bytes).

Makefile.in
RtAudio.cpp
RtAudio.h
configure.ac
doc/release.txt
include/iasiothiscallresolver.cpp
include/iasiothiscallresolver.h
tests/Makefile.in
tests/duplex.cpp
tests/playraw.cpp

index 5429b773186b05e072030ebe4c06006ad5a39188..10b7ac39d852da5aa972a27747f77cbfe284988d 100644 (file)
@@ -2,11 +2,13 @@
 ### RtAudio library Makefile
 
 RM = /bin/rm
+LN = /bin/ln
 
 OBJECTS        = RtAudio.o @objects@
 
 STATIC = librtaudio.a
-SHARED = librtaudio.so
+SHARED = @sharedlib@
+RELEASE = 4.0.7
 LIBRARIES = $(STATIC) $(SHARED)
 
 CC       = @CXX@
@@ -24,7 +26,10 @@ tests:
 $(LIBRARIES): $(OBJECTS)
        $(AR) ruv $(STATIC) $(OBJECTS)
        ranlib $(STATIC)
-       $(CC) -shared $(OBJECTS) -o $(SHARED) @LIBS@
+       $(CC) -fPIC @libflags@ $(OBJECTS) @LIBS@
+       $(LN) -s @sharedname@ $(SHARED)
+
+#      $(CC) -shared $(OBJECTS) -o $(SHARED) @LIBS@
 
 %.o : %.cpp
        $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $@
@@ -33,12 +38,15 @@ $(LIBRARIES): $(OBJECTS)
        $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $@
 
 clean : 
-       $(RM) -f $(LIBRARIES)
+       $(RM) -f $(LIBRARIES) @sharedname@ $(SHARED)*
        $(RM) -f $(OBJECTS)
        $(RM) -f *~
        cd tests && $(MAKE) clean
 
-distclean: clean
+distclean:
+       $(RM) -f $(LIBRARIES) @sharedname@ $(SHARED)*
+       $(RM) -f $(OBJECTS)
+       $(RM) -f *~
        $(RM) -rf config.log config.status autom4te.cache Makefile rtaudio-config
        cd tests && $(MAKE) distclean
 
index 9ac6c5b0a41d0e7b22852fe090fa5e3170bd0526..028fffa3b92b9029189fdadfa08b862ba920cda2 100644 (file)
@@ -10,7 +10,7 @@
     RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
 
     RtAudio: realtime audio i/o C++ classes
-    Copyright (c) 2001-2010 Gary P. Scavone
+    Copyright (c) 2001-2011 Gary P. Scavone
 
     Permission is hereby granted, free of charge, to any person
     obtaining a copy of this software and associated documentation files
@@ -38,7 +38,7 @@
 */
 /************************************************************************/
 
-// RtAudio: Version 4.0.7
+// RtAudio: Version 4.0.8
 
 #include "RtAudio.h"
 #include <iostream>
@@ -557,10 +557,14 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
     return info;
   }
 
-  const char *mname = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );
+  //const char *mname = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );
+  int length = CFStringGetLength(cfname);
+  char *mname = (char *)malloc(length * 3 + 1);
+  CFStringGetCString(cfname, mname, length * 3 + 1, CFStringGetSystemEncoding());
   info.name.append( (const char *)mname, strlen(mname) );
   info.name.append( ": " );
   CFRelease( cfname );
+  free(mname);
 
   property.mSelector = kAudioObjectPropertyName;
   result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname );
@@ -571,9 +575,13 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
     return info;
   }
 
-  const char *name = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );
+  //const char *name = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );
+  length = CFStringGetLength(cfname);
+  char *name = (char *)malloc(length * 3 + 1);
+  CFStringGetCString(cfname, name, length * 3 + 1, CFStringGetSystemEncoding());
   info.name.append( (const char *)name, strlen(name) );
   CFRelease( cfname );
+  free(name);
 
   // Get the output stream "configuration".
   AudioBufferList      *bufferList = nil;
@@ -1392,7 +1400,9 @@ void RtApiCore :: stopStream( void )
 
   if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
 
+    MUTEX_UNLOCK( &stream_.mutex );
     result = AudioDeviceStop( handle->id[1], callbackHandler );
+    MUTEX_LOCK( &stream_.mutex );
     if ( result != noErr ) {
       errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping input callback procedure on device (" << stream_.device[1] << ").";
       errorText_ = errorStream_.str();
@@ -1472,6 +1482,7 @@ bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
       status |= RTAUDIO_INPUT_OVERFLOW;
       handle->xrun[1] = false;
     }
+
     handle->drainCounter = callback( stream_.userBuffer[0], stream_.userBuffer[1],
                                      stream_.bufferSize, streamTime, status, info->userData );
     if ( handle->drainCounter == 2 ) {
@@ -7393,7 +7404,7 @@ void RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info
 {
   // This function does format conversion, input/output channel compensation, and
   // data interleaving/deinterleaving.  24-bit integers are assumed to occupy
-  // the upper three bytes of a 32-bit integer.
+  // the lower three bytes of a 32-bit integer.
 
   // Clear our device buffer when in/out duplex device channels are different
   if ( outBuffer == stream_.deviceBuffer && stream_.mode == DUPLEX &&
@@ -7581,7 +7592,7 @@ void RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info
         out += info.outJump;
       }
     }
-    else if (info.inFormat == RTAUDIO_SINT24) {
+    else if (info.inFormat == RTAUDIO_SINT24) { // Hmmm ... we could just leave it in the lower 3 bytes
       Int32 *in = (Int32 *)inBuffer;
       for (unsigned int i=0; i<stream_.bufferSize; i++) {
         for (j=0; j<info.channels; j++) {
index feb26a3213f77280c0ecde11c2c5314b549c0251..d1624cfe0239b16ab125230b66ed7928c017c357 100644 (file)
--- a/RtAudio.h
+++ b/RtAudio.h
@@ -10,7 +10,7 @@
     RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
 
     RtAudio: realtime audio i/o C++ classes
-    Copyright (c) 2001-2010 Gary P. Scavone
+    Copyright (c) 2001-2011 Gary P. Scavone
 
     Permission is hereby granted, free of charge, to any person
     obtaining a copy of this software and associated documentation files
@@ -42,7 +42,7 @@
   \file RtAudio.h
  */
 
-// RtAudio: Version 4.0.7
+// RtAudio: Version 4.0.8
 
 #ifndef __RTAUDIO_H
 #define __RTAUDIO_H
     internal routines will automatically take care of any necessary
     byte-swapping between the host format and the soundcard.  Thus,
     endian-ness is not a concern in the following format definitions.
+    Note that 24-bit data is expected to be encapsulated in a 32-bit
+    format.
 
     - \e RTAUDIO_SINT8:   8-bit signed integer.
     - \e RTAUDIO_SINT16:  16-bit signed integer.
-    - \e RTAUDIO_SINT24:  Upper 3 bytes of 32-bit signed integer.
+    - \e RTAUDIO_SINT24:  Lower 3 bytes of 32-bit signed integer.
     - \e RTAUDIO_SINT32:  32-bit signed integer.
     - \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0.
     - \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0.
index 616ad54db0807019a38c33085481314405bd1680..422d257daf17a3c37ac72b80bc9344eaeb4dec10 100644 (file)
@@ -44,9 +44,20 @@ fi
 
 CXXFLAGS="$CXXFLAGS $cxxflag"
 
+AC_CANONICAL_HOST
+
+AC_SUBST( sharedlib, ["librtaudio.so"] )
+AC_SUBST( sharedname, ["librtaudio.so.\$(RELEASE)"] )
+AC_SUBST( libflags, ["-shared -Wl,-soname,\$(SHAREDLIB).\$(MAJOR) -o \$(SHAREDLIB).\$(RELEASE)"] )
+case $host in
+  *-apple*)
+  AC_SUBST( sharedlib, ["librtaudio.dylib"] )
+  AC_SUBST( sharedname, ["librtaudio.\$(RELEASE).dylib"] )
+  AC_SUBST( libflags, ["-dynamiclib -o librtaudio.\$(RELEASE).dylib"] )
+esac
+
 # Checks for package options and external software
 AC_SUBST( api, [""] )
-AC_CANONICAL_HOST
 AC_MSG_CHECKING(for audio API)
 case $host in
   *-*-netbsd*)
index 3165e3d8eed21d4dfcff703c675ee26c8b911851..06d5b0c6c353c4622691c3fe1b25b0ae317f5dbf 100644 (file)
@@ -1,6 +1,10 @@
 RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems.
 
-By Gary P. Scavone, 2001-2010.
+By Gary P. Scavone, 2001-2011.
+
+v4.0.8: (?? February 2011)
+- fix for MinGW4 problem enumerating and setting sample rates
+
 
 v4.0.7: (4 February 2010)
 - revised Windows DS code and device enumeration to speed up device queries
index 38c39d2e7f0863d3e898b358544d798b509886fc..08c55eacfc67adc541202f9fb2056593feb50a7f 100644 (file)
-/*\r
-       IASIOThiscallResolver.cpp see the comments in iasiothiscallresolver.h for\r
-    the top level description - this comment describes the technical details of\r
-    the implementation.\r
-\r
-    The latest version of this file is available from:\r
-    http://www.audiomulch.com/~rossb/code/calliasio\r
-\r
-    please email comments to Ross Bencina <rossb@audiomulch.com>\r
-\r
-    BACKGROUND\r
-\r
-    The IASIO interface declared in the Steinberg ASIO 2 SDK declares\r
-    functions with no explicit calling convention. This causes MSVC++ to default\r
-    to using the thiscall convention, which is a proprietary convention not\r
-    implemented by some non-microsoft compilers - notably borland BCC,\r
-    C++Builder, and gcc. MSVC++ is the defacto standard compiler used by\r
-    Steinberg. As a result of this situation, the ASIO sdk will compile with\r
-    any compiler, however attempting to execute the compiled code will cause a\r
-    crash due to different default calling conventions on non-Microsoft\r
-    compilers.\r
-\r
-    IASIOThiscallResolver solves the problem by providing an adapter class that\r
-    delegates to the IASIO interface using the correct calling convention\r
-    (thiscall). Due to the lack of support for thiscall in the Borland and GCC\r
-    compilers, the calls have been implemented in assembly language.\r
-\r
-    A number of macros are defined for thiscall function calls with different\r
-    numbers of parameters, with and without return values - it may be possible\r
-    to modify the format of these macros to make them work with other inline\r
-    assemblers.\r
-\r
-\r
-    THISCALL DEFINITION\r
-\r
-    A number of definitions of the thiscall calling convention are floating\r
-    around the internet. The following definition has been validated against\r
-    output from the MSVC++ compiler:\r
-\r
-    For non-vararg functions, thiscall works as follows: the object (this)\r
-    pointer is passed in ECX. All arguments are passed on the stack in\r
-    right to left order. The return value is placed in EAX. The callee\r
-    clears the passed arguments from the stack.\r
-\r
-\r
-    FINDING FUNCTION POINTERS FROM AN IASIO POINTER\r
-\r
-    The first field of a COM object is a pointer to its vtble. Thus a pointer\r
-    to an object implementing the IASIO interface also points to a pointer to\r
-    that object's vtbl. The vtble is a table of function pointers for all of\r
-    the virtual functions exposed by the implemented interfaces.\r
-\r
-    If we consider a variable declared as a pointer to IASO:\r
-\r
-    IASIO *theAsioDriver\r
-\r
-    theAsioDriver points to:\r
-\r
-    object implementing IASIO\r
-    {\r
-        IASIOvtbl *vtbl\r
-        other data\r
-    }\r
-\r
-    in other words, theAsioDriver points to a pointer to an IASIOvtbl\r
-\r
-    vtbl points to a table of function pointers:\r
-\r
-    IASIOvtbl ( interface IASIO : public IUnknown )\r
-    {\r
-    (IUnknown functions)\r
-    0   virtual HRESULT STDMETHODCALLTYPE (*QueryInterface)(REFIID riid, void **ppv) = 0;\r
-    4   virtual ULONG STDMETHODCALLTYPE (*AddRef)() = 0;\r
-    8   virtual ULONG STDMETHODCALLTYPE (*Release)() = 0;      \r
-\r
-    (IASIO functions)\r
-    12 virtual ASIOBool (*init)(void *sysHandle) = 0;\r
-    16 virtual void (*getDriverName)(char *name) = 0;\r
-    20 virtual long (*getDriverVersion)() = 0;\r
-    24 virtual void (*getErrorMessage)(char *string) = 0;\r
-    28 virtual ASIOError (*start)() = 0;\r
-    32 virtual ASIOError (*stop)() = 0;\r
-    36 virtual ASIOError (*getChannels)(long *numInputChannels, long *numOutputChannels) = 0;\r
-    40 virtual ASIOError (*getLatencies)(long *inputLatency, long *outputLatency) = 0;\r
-    44 virtual ASIOError (*getBufferSize)(long *minSize, long *maxSize,\r
-            long *preferredSize, long *granularity) = 0;\r
-    48 virtual ASIOError (*canSampleRate)(ASIOSampleRate sampleRate) = 0;\r
-    52 virtual ASIOError (*getSampleRate)(ASIOSampleRate *sampleRate) = 0;\r
-    56 virtual ASIOError (*setSampleRate)(ASIOSampleRate sampleRate) = 0;\r
-    60 virtual ASIOError (*getClockSources)(ASIOClockSource *clocks, long *numSources) = 0;\r
-    64 virtual ASIOError (*setClockSource)(long reference) = 0;\r
-    68 virtual ASIOError (*getSamplePosition)(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;\r
-    72 virtual ASIOError (*getChannelInfo)(ASIOChannelInfo *info) = 0;\r
-    76 virtual ASIOError (*createBuffers)(ASIOBufferInfo *bufferInfos, long numChannels,\r
-            long bufferSize, ASIOCallbacks *callbacks) = 0;\r
-    80 virtual ASIOError (*disposeBuffers)() = 0;\r
-    84 virtual ASIOError (*controlPanel)() = 0;\r
-    88 virtual ASIOError (*future)(long selector,void *opt) = 0;\r
-    92 virtual ASIOError (*outputReady)() = 0;\r
-    };\r
-\r
-    The numbers in the left column show the byte offset of each function ptr\r
-    from the beginning of the vtbl. These numbers are used in the code below\r
-    to select different functions.\r
-\r
-    In order to find the address of a particular function, theAsioDriver\r
-    must first be dereferenced to find the value of the vtbl pointer:\r
-\r
-    mov     eax, theAsioDriver\r
-    mov     edx, [theAsioDriver]  // edx now points to vtbl[0]\r
-\r
-    Then an offset must be added to the vtbl pointer to select a\r
-    particular function, for example vtbl+44 points to the slot containing\r
-    a pointer to the getBufferSize function.\r
-\r
-    Finally vtbl+x must be dereferenced to obtain the value of the function\r
-    pointer stored in that address:\r
-\r
-    call    [edx+44]    // call the function pointed to by\r
-                        // the value in the getBufferSize field of the vtbl\r
-\r
-\r
-    SEE ALSO\r
-\r
-    Martin Fay's OpenASIO DLL at http://www.martinfay.com solves the same\r
-    problem by providing a new COM interface which wraps IASIO with an\r
-    interface that uses portable calling conventions. OpenASIO must be compiled\r
-    with MSVC, and requires that you ship the OpenASIO DLL with your\r
-    application.\r
-\r
-    \r
-    ACKNOWLEDGEMENTS\r
-\r
-    Ross Bencina: worked out the thiscall details above, wrote the original\r
-    Borland asm macros, and a patch for asio.cpp (which is no longer needed).\r
-    Thanks to Martin Fay for introducing me to the issues discussed here,\r
-    and to Rene G. Ceballos for assisting with asm dumps from MSVC++.\r
-\r
-    Antti Silvast: converted the original calliasio to work with gcc and NASM\r
-    by implementing the asm code in a separate file.\r
-\r
-       Fraser Adams: modified the original calliasio containing the Borland inline\r
-    asm to add inline asm for gcc i.e. Intel syntax for Borland and AT&T syntax\r
-    for gcc. This seems a neater approach for gcc than to have a separate .asm\r
-    file and it means that we only need one version of the thiscall patch.\r
-\r
-    Fraser Adams: rewrote the original calliasio patch in the form of the\r
-    IASIOThiscallResolver class in order to avoid modifications to files from\r
-    the Steinberg SDK, which may have had potential licence issues.\r
-\r
-    Andrew Baldwin: contributed fixes for compatibility problems with more\r
-    recent versions of the gcc assembler.\r
-*/\r
-\r
-\r
-// We only need IASIOThiscallResolver at all if we are on Win32. For other\r
-// platforms we simply bypass the IASIOThiscallResolver definition to allow us\r
-// to be safely #include'd whatever the platform to keep client code portable\r
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)\r
-\r
-\r
-// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver\r
-// is not used.\r
-#if !defined(_MSC_VER)\r
-\r
-\r
-#include <new>\r
-#include <assert.h>\r
-\r
-// We have a mechanism in iasiothiscallresolver.h to ensure that asio.h is\r
-// #include'd before it in client code, we do NOT want to do this test here.\r
-#define iasiothiscallresolver_sourcefile 1\r
-#include "iasiothiscallresolver.h"\r
-#undef iasiothiscallresolver_sourcefile\r
-\r
-// iasiothiscallresolver.h redefines ASIOInit for clients, but we don't want\r
-// this macro defined in this translation unit.\r
-#undef ASIOInit\r
-\r
-\r
-// theAsioDriver is a global pointer to the current IASIO instance which the\r
-// ASIO SDK uses to perform all actions on the IASIO interface. We substitute\r
-// our own forwarding interface into this pointer.\r
-extern IASIO* theAsioDriver;\r
-\r
-\r
-// The following macros define the inline assembler for BORLAND first then gcc\r
-\r
-#if defined(__BCPLUSPLUS__) || defined(__BORLANDC__)          \r
-\r
-\r
-#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )\\r
-    void *this_ = (thisPtr);                                                \\r
-    __asm {                                                                 \\r
-        mov     ecx, this_            ;                                     \\r
-        mov     eax, [ecx]            ;                                     \\r
-        call    [eax+funcOffset]      ;                                     \\r
-        mov     resultName, eax       ;                                     \\r
-    }\r
-\r
-\r
-#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )\\r
-    void *this_ = (thisPtr);                                                \\r
-    __asm {                                                                 \\r
-        mov     eax, param1           ;                                     \\r
-        push    eax                   ;                                     \\r
-        mov     ecx, this_            ;                                     \\r
-        mov     eax, [ecx]            ;                                     \\r
-        call    [eax+funcOffset]      ;                                     \\r
-    }\r
-\r
-\r
-#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )\\r
-    void *this_ = (thisPtr);                                                \\r
-    __asm {                                                                 \\r
-        mov     eax, param1           ;                                     \\r
-        push    eax                   ;                                     \\r
-        mov     ecx, this_            ;                                     \\r
-        mov     eax, [ecx]            ;                                     \\r
-        call    [eax+funcOffset]      ;                                     \\r
-        mov     resultName, eax       ;                                     \\r
-    }\r
-\r
-\r
-#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )\\r
-    void *this_ = (thisPtr);                                                \\r
-    void *doubleParamPtr_ (&param1);                                        \\r
-    __asm {                                                                 \\r
-        mov     eax, doubleParamPtr_  ;                                     \\r
-        push    [eax+4]               ;                                     \\r
-        push    [eax]                 ;                                     \\r
-        mov     ecx, this_            ;                                     \\r
-        mov     eax, [ecx]            ;                                     \\r
-        call    [eax+funcOffset]      ;                                     \\r
-        mov     resultName, eax       ;                                     \\r
-    }\r
-\r
-\r
-#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )\\r
-    void *this_ = (thisPtr);                                                \\r
-    __asm {                                                                 \\r
-        mov     eax, param2           ;                                     \\r
-        push    eax                   ;                                     \\r
-        mov     eax, param1           ;                                     \\r
-        push    eax                   ;                                     \\r
-        mov     ecx, this_            ;                                     \\r
-        mov     eax, [ecx]            ;                                     \\r
-        call    [eax+funcOffset]      ;                                     \\r
-        mov     resultName, eax       ;                                     \\r
-    }\r
-\r
-\r
-#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\\r
-    void *this_ = (thisPtr);                                                \\r
-    __asm {                                                                 \\r
-        mov     eax, param4           ;                                     \\r
-        push    eax                   ;                                     \\r
-        mov     eax, param3           ;                                     \\r
-        push    eax                   ;                                     \\r
-        mov     eax, param2           ;                                     \\r
-        push    eax                   ;                                     \\r
-        mov     eax, param1           ;                                     \\r
-        push    eax                   ;                                     \\r
-        mov     ecx, this_            ;                                     \\r
-        mov     eax, [ecx]            ;                                     \\r
-        call    [eax+funcOffset]      ;                                     \\r
-        mov     resultName, eax       ;                                     \\r
-    }\r
-\r
-\r
-#elif defined(__GNUC__)\r
-\r
-\r
-#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )                  \\r
-    __asm__ __volatile__ ("movl (%1), %%edx\n\t"                            \\r
-                          "call *"#funcOffset"(%%edx)\n\t"                  \\r
-                          :"=a"(resultName) /* Output Operands */           \\r
-                          :"c"(thisPtr)     /* Input Operands */            \\r
-                         );                                                 \\r
-\r
-\r
-#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )                 \\r
-    __asm__ __volatile__ ("pushl %0\n\t"                                    \\r
-                          "movl (%1), %%edx\n\t"                            \\r
-                          "call *"#funcOffset"(%%edx)\n\t"                  \\r
-                          :                 /* Output Operands */           \\r
-                          :"r"(param1),     /* Input Operands */            \\r
-                           "c"(thisPtr)                                     \\r
-                         );                                                 \\r
-\r
-\r
-#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )          \\r
-    __asm__ __volatile__ ("pushl %1\n\t"                                    \\r
-                          "movl (%2), %%edx\n\t"                            \\r
-                          "call *"#funcOffset"(%%edx)\n\t"                  \\r
-                          :"=a"(resultName) /* Output Operands */           \\r
-                          :"r"(param1),     /* Input Operands */            \\r
-                           "c"(thisPtr)                                     \\r
-                          );                                                \\r
-\r
-\r
-#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )   \\r
-    __asm__ __volatile__ ("pushl 4(%1)\n\t"                                 \\r
-                          "pushl (%1)\n\t"                                  \\r
-                          "movl (%2), %%edx\n\t"                            \\r
-                          "call *"#funcOffset"(%%edx);\n\t"                 \\r
-                          :"=a"(resultName) /* Output Operands */           \\r
-                          :"a"(&param1),    /* Input Operands */            \\r
-                           /* Note: Using "r" above instead of "a" fails */ \\r
-                           /* when using GCC 3.3.3, and maybe later versions*/\\r
-                           "c"(thisPtr)                                     \\r
-                          );                                                \\r
-\r
-\r
-#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )  \\r
-    __asm__ __volatile__ ("pushl %1\n\t"                                    \\r
-                          "pushl %2\n\t"                                    \\r
-                          "movl (%3), %%edx\n\t"                            \\r
-                          "call *"#funcOffset"(%%edx)\n\t"                  \\r
-                          :"=a"(resultName) /* Output Operands */           \\r
-                          :"r"(param2),     /* Input Operands */            \\r
-                           "r"(param1),                                     \\r
-                           "c"(thisPtr)                                     \\r
-                          );                                                \\r
-\r
-\r
-#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\\r
-    __asm__ __volatile__ ("pushl %1\n\t"                                    \\r
-                          "pushl %2\n\t"                                    \\r
-                          "pushl %3\n\t"                                    \\r
-                          "pushl %4\n\t"                                    \\r
-                          "movl (%5), %%edx\n\t"                            \\r
-                          "call *"#funcOffset"(%%edx)\n\t"                  \\r
-                          :"=a"(resultName) /* Output Operands */           \\r
-                          :"r"(param4),     /* Input Operands  */           \\r
-                           "r"(param3),                                     \\r
-                           "r"(param2),                                     \\r
-                           "r"(param1),                                     \\r
-                           "c"(thisPtr)                                     \\r
-                          );                                                \\r
-\r
-#endif\r
-\r
-\r
-\r
-// Our static singleton instance.\r
-IASIOThiscallResolver IASIOThiscallResolver::instance;\r
-\r
-// Constructor called to initialize static Singleton instance above. Note that\r
-// it is important not to clear that_ incase it has already been set by the call\r
-// to placement new in ASIOInit().\r
-IASIOThiscallResolver::IASIOThiscallResolver()\r
-{\r
-}\r
-\r
-// Constructor called from ASIOInit() below\r
-IASIOThiscallResolver::IASIOThiscallResolver(IASIO* that)\r
-: that_( that )\r
-{\r
-}\r
-\r
-// Implement IUnknown methods as assert(false). IASIOThiscallResolver is not\r
-// really a COM object, just a wrapper which will work with the ASIO SDK.\r
-// If you wanted to use ASIO without the SDK you might want to implement COM\r
-// aggregation in these methods.\r
-HRESULT STDMETHODCALLTYPE IASIOThiscallResolver::QueryInterface(REFIID riid, void **ppv)\r
-{\r
-    (void)riid;     // suppress unused variable warning\r
-\r
-    assert( false ); // this function should never be called by the ASIO SDK.\r
-\r
-    *ppv = NULL;\r
-    return E_NOINTERFACE;\r
-}\r
-\r
-ULONG STDMETHODCALLTYPE IASIOThiscallResolver::AddRef()\r
-{\r
-    assert( false ); // this function should never be called by the ASIO SDK.\r
-\r
-    return 1;\r
-}\r
-\r
-ULONG STDMETHODCALLTYPE IASIOThiscallResolver::Release()\r
-{\r
-    assert( false ); // this function should never be called by the ASIO SDK.\r
-    \r
-    return 1;\r
-}\r
-\r
-\r
-// Implement the IASIO interface methods by performing the vptr manipulation\r
-// described above then delegating to the real implementation.\r
-ASIOBool IASIOThiscallResolver::init(void *sysHandle)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_1( result, that_, 12, sysHandle );\r
-    return result;\r
-}\r
-\r
-void IASIOThiscallResolver::getDriverName(char *name)\r
-{\r
-    CALL_VOID_THISCALL_1( that_, 16, name );\r
-}\r
-\r
-long IASIOThiscallResolver::getDriverVersion()\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_0( result, that_, 20 );\r
-    return result;\r
-}\r
-\r
-void IASIOThiscallResolver::getErrorMessage(char *string)\r
-{\r
-     CALL_VOID_THISCALL_1( that_, 24, string );\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::start()\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_0( result, that_, 28 );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::stop()\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_0( result, that_, 32 );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::getChannels(long *numInputChannels, long *numOutputChannels)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_2( result, that_, 36, numInputChannels, numOutputChannels );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::getLatencies(long *inputLatency, long *outputLatency)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_2( result, that_, 40, inputLatency, outputLatency );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::getBufferSize(long *minSize, long *maxSize,\r
-        long *preferredSize, long *granularity)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_4( result, that_, 44, minSize, maxSize, preferredSize, granularity );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::canSampleRate(ASIOSampleRate sampleRate)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_1_DOUBLE( result, that_, 48, sampleRate );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::getSampleRate(ASIOSampleRate *sampleRate)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_1( result, that_, 52, sampleRate );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::setSampleRate(ASIOSampleRate sampleRate)\r
-{    \r
-    ASIOBool result;\r
-    CALL_THISCALL_1_DOUBLE( result, that_, 56, sampleRate );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::getClockSources(ASIOClockSource *clocks, long *numSources)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_2( result, that_, 60, clocks, numSources );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::setClockSource(long reference)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_1( result, that_, 64, reference );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_2( result, that_, 68, sPos, tStamp );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::getChannelInfo(ASIOChannelInfo *info)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_1( result, that_, 72, info );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::createBuffers(ASIOBufferInfo *bufferInfos,\r
-        long numChannels, long bufferSize, ASIOCallbacks *callbacks)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_4( result, that_, 76, bufferInfos, numChannels, bufferSize, callbacks );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::disposeBuffers()\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_0( result, that_, 80 );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::controlPanel()\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_0( result, that_, 84 );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::future(long selector,void *opt)\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_2( result, that_, 88, selector, opt );\r
-    return result;\r
-}\r
-\r
-ASIOError IASIOThiscallResolver::outputReady()\r
-{\r
-    ASIOBool result;\r
-    CALL_THISCALL_0( result, that_, 92 );\r
-    return result;\r
-}\r
-\r
-\r
-// Implement our substitute ASIOInit() method\r
-ASIOError IASIOThiscallResolver::ASIOInit(ASIODriverInfo *info)\r
-{\r
-    // To ensure that our instance's vptr is correctly constructed, even if\r
-    // ASIOInit is called prior to main(), we explicitly call its constructor\r
-    // (potentially over the top of an existing instance). Note that this is\r
-    // pretty ugly, and is only safe because IASIOThiscallResolver has no\r
-    // destructor and contains no objects with destructors.\r
-    new((void*)&instance) IASIOThiscallResolver( theAsioDriver );\r
-\r
-    // Interpose between ASIO client code and the real driver.\r
-    theAsioDriver = &instance;\r
-\r
-    // Note that we never need to switch theAsioDriver back to point to the\r
-    // real driver because theAsioDriver is reset to zero in ASIOExit().\r
-\r
-    // Delegate to the real ASIOInit\r
-       return ::ASIOInit(info);\r
-}\r
-\r
-\r
-#endif /* !defined(_MSC_VER) */\r
-\r
-#endif /* Win32 */\r
-\r
+/*
+       IASIOThiscallResolver.cpp see the comments in iasiothiscallresolver.h for
+    the top level description - this comment describes the technical details of
+    the implementation.
+
+    The latest version of this file is available from:
+    http://www.audiomulch.com/~rossb/code/calliasio
+
+    please email comments to Ross Bencina <rossb@audiomulch.com>
+
+    BACKGROUND
+
+    The IASIO interface declared in the Steinberg ASIO 2 SDK declares
+    functions with no explicit calling convention. This causes MSVC++ to default
+    to using the thiscall convention, which is a proprietary convention not
+    implemented by some non-microsoft compilers - notably borland BCC,
+    C++Builder, and gcc. MSVC++ is the defacto standard compiler used by
+    Steinberg. As a result of this situation, the ASIO sdk will compile with
+    any compiler, however attempting to execute the compiled code will cause a
+    crash due to different default calling conventions on non-Microsoft
+    compilers.
+
+    IASIOThiscallResolver solves the problem by providing an adapter class that
+    delegates to the IASIO interface using the correct calling convention
+    (thiscall). Due to the lack of support for thiscall in the Borland and GCC
+    compilers, the calls have been implemented in assembly language.
+
+    A number of macros are defined for thiscall function calls with different
+    numbers of parameters, with and without return values - it may be possible
+    to modify the format of these macros to make them work with other inline
+    assemblers.
+
+
+    THISCALL DEFINITION
+
+    A number of definitions of the thiscall calling convention are floating
+    around the internet. The following definition has been validated against
+    output from the MSVC++ compiler:
+
+    For non-vararg functions, thiscall works as follows: the object (this)
+    pointer is passed in ECX. All arguments are passed on the stack in
+    right to left order. The return value is placed in EAX. The callee
+    clears the passed arguments from the stack.
+
+
+    FINDING FUNCTION POINTERS FROM AN IASIO POINTER
+
+    The first field of a COM object is a pointer to its vtble. Thus a pointer
+    to an object implementing the IASIO interface also points to a pointer to
+    that object's vtbl. The vtble is a table of function pointers for all of
+    the virtual functions exposed by the implemented interfaces.
+
+    If we consider a variable declared as a pointer to IASO:
+
+    IASIO *theAsioDriver
+
+    theAsioDriver points to:
+
+    object implementing IASIO
+    {
+        IASIOvtbl *vtbl
+        other data
+    }
+
+    in other words, theAsioDriver points to a pointer to an IASIOvtbl
+
+    vtbl points to a table of function pointers:
+
+    IASIOvtbl ( interface IASIO : public IUnknown )
+    {
+    (IUnknown functions)
+    0   virtual HRESULT STDMETHODCALLTYPE (*QueryInterface)(REFIID riid, void **ppv) = 0;
+    4   virtual ULONG STDMETHODCALLTYPE (*AddRef)() = 0;
+    8   virtual ULONG STDMETHODCALLTYPE (*Release)() = 0;      
+
+    (IASIO functions)
+    12 virtual ASIOBool (*init)(void *sysHandle) = 0;
+    16 virtual void (*getDriverName)(char *name) = 0;
+    20 virtual long (*getDriverVersion)() = 0;
+    24 virtual void (*getErrorMessage)(char *string) = 0;
+    28 virtual ASIOError (*start)() = 0;
+    32 virtual ASIOError (*stop)() = 0;
+    36 virtual ASIOError (*getChannels)(long *numInputChannels, long *numOutputChannels) = 0;
+    40 virtual ASIOError (*getLatencies)(long *inputLatency, long *outputLatency) = 0;
+    44 virtual ASIOError (*getBufferSize)(long *minSize, long *maxSize,
+            long *preferredSize, long *granularity) = 0;
+    48 virtual ASIOError (*canSampleRate)(ASIOSampleRate sampleRate) = 0;
+    52 virtual ASIOError (*getSampleRate)(ASIOSampleRate *sampleRate) = 0;
+    56 virtual ASIOError (*setSampleRate)(ASIOSampleRate sampleRate) = 0;
+    60 virtual ASIOError (*getClockSources)(ASIOClockSource *clocks, long *numSources) = 0;
+    64 virtual ASIOError (*setClockSource)(long reference) = 0;
+    68 virtual ASIOError (*getSamplePosition)(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
+    72 virtual ASIOError (*getChannelInfo)(ASIOChannelInfo *info) = 0;
+    76 virtual ASIOError (*createBuffers)(ASIOBufferInfo *bufferInfos, long numChannels,
+            long bufferSize, ASIOCallbacks *callbacks) = 0;
+    80 virtual ASIOError (*disposeBuffers)() = 0;
+    84 virtual ASIOError (*controlPanel)() = 0;
+    88 virtual ASIOError (*future)(long selector,void *opt) = 0;
+    92 virtual ASIOError (*outputReady)() = 0;
+    };
+
+    The numbers in the left column show the byte offset of each function ptr
+    from the beginning of the vtbl. These numbers are used in the code below
+    to select different functions.
+
+    In order to find the address of a particular function, theAsioDriver
+    must first be dereferenced to find the value of the vtbl pointer:
+
+    mov     eax, theAsioDriver
+    mov     edx, [theAsioDriver]  // edx now points to vtbl[0]
+
+    Then an offset must be added to the vtbl pointer to select a
+    particular function, for example vtbl+44 points to the slot containing
+    a pointer to the getBufferSize function.
+
+    Finally vtbl+x must be dereferenced to obtain the value of the function
+    pointer stored in that address:
+
+    call    [edx+44]    // call the function pointed to by
+                        // the value in the getBufferSize field of the vtbl
+
+
+    SEE ALSO
+
+    Martin Fay's OpenASIO DLL at http://www.martinfay.com solves the same
+    problem by providing a new COM interface which wraps IASIO with an
+    interface that uses portable calling conventions. OpenASIO must be compiled
+    with MSVC, and requires that you ship the OpenASIO DLL with your
+    application.
+
+    
+    ACKNOWLEDGEMENTS
+
+    Ross Bencina: worked out the thiscall details above, wrote the original
+    Borland asm macros, and a patch for asio.cpp (which is no longer needed).
+    Thanks to Martin Fay for introducing me to the issues discussed here,
+    and to Rene G. Ceballos for assisting with asm dumps from MSVC++.
+
+    Antti Silvast: converted the original calliasio to work with gcc and NASM
+    by implementing the asm code in a separate file.
+
+       Fraser Adams: modified the original calliasio containing the Borland inline
+    asm to add inline asm for gcc i.e. Intel syntax for Borland and AT&T syntax
+    for gcc. This seems a neater approach for gcc than to have a separate .asm
+    file and it means that we only need one version of the thiscall patch.
+
+    Fraser Adams: rewrote the original calliasio patch in the form of the
+    IASIOThiscallResolver class in order to avoid modifications to files from
+    the Steinberg SDK, which may have had potential licence issues.
+
+    Andrew Baldwin: contributed fixes for compatibility problems with more
+    recent versions of the gcc assembler.
+*/
+
+
+// We only need IASIOThiscallResolver at all if we are on Win32. For other
+// platforms we simply bypass the IASIOThiscallResolver definition to allow us
+// to be safely #include'd whatever the platform to keep client code portable
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)
+
+
+// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
+// is not used.
+#if !defined(_MSC_VER)
+
+
+#include <new>
+#include <assert.h>
+
+// We have a mechanism in iasiothiscallresolver.h to ensure that asio.h is
+// #include'd before it in client code, we do NOT want to do this test here.
+#define iasiothiscallresolver_sourcefile 1
+#include "iasiothiscallresolver.h"
+#undef iasiothiscallresolver_sourcefile
+
+// iasiothiscallresolver.h redefines ASIOInit for clients, but we don't want
+// this macro defined in this translation unit.
+#undef ASIOInit
+
+
+// theAsioDriver is a global pointer to the current IASIO instance which the
+// ASIO SDK uses to perform all actions on the IASIO interface. We substitute
+// our own forwarding interface into this pointer.
+extern IASIO* theAsioDriver;
+
+
+// The following macros define the inline assembler for BORLAND first then gcc
+
+#if defined(__BCPLUSPLUS__) || defined(__BORLANDC__)          
+
+
+#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )\
+    void *this_ = (thisPtr);                                                \
+    __asm {                                                                 \
+        mov     ecx, this_            ;                                     \
+        mov     eax, [ecx]            ;                                     \
+        call    [eax+funcOffset]      ;                                     \
+        mov     resultName, eax       ;                                     \
+    }
+
+
+#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )\
+    void *this_ = (thisPtr);                                                \
+    __asm {                                                                 \
+        mov     eax, param1           ;                                     \
+        push    eax                   ;                                     \
+        mov     ecx, this_            ;                                     \
+        mov     eax, [ecx]            ;                                     \
+        call    [eax+funcOffset]      ;                                     \
+    }
+
+
+#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )\
+    void *this_ = (thisPtr);                                                \
+    __asm {                                                                 \
+        mov     eax, param1           ;                                     \
+        push    eax                   ;                                     \
+        mov     ecx, this_            ;                                     \
+        mov     eax, [ecx]            ;                                     \
+        call    [eax+funcOffset]      ;                                     \
+        mov     resultName, eax       ;                                     \
+    }
+
+
+#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )\
+    void *this_ = (thisPtr);                                                \
+    void *doubleParamPtr_ (&param1);                                        \
+    __asm {                                                                 \
+        mov     eax, doubleParamPtr_  ;                                     \
+        push    [eax+4]               ;                                     \
+        push    [eax]                 ;                                     \
+        mov     ecx, this_            ;                                     \
+        mov     eax, [ecx]            ;                                     \
+        call    [eax+funcOffset]      ;                                     \
+        mov     resultName, eax       ;                                     \
+    }
+
+
+#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )\
+    void *this_ = (thisPtr);                                                \
+    __asm {                                                                 \
+        mov     eax, param2           ;                                     \
+        push    eax                   ;                                     \
+        mov     eax, param1           ;                                     \
+        push    eax                   ;                                     \
+        mov     ecx, this_            ;                                     \
+        mov     eax, [ecx]            ;                                     \
+        call    [eax+funcOffset]      ;                                     \
+        mov     resultName, eax       ;                                     \
+    }
+
+
+#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
+    void *this_ = (thisPtr);                                                \
+    __asm {                                                                 \
+        mov     eax, param4           ;                                     \
+        push    eax                   ;                                     \
+        mov     eax, param3           ;                                     \
+        push    eax                   ;                                     \
+        mov     eax, param2           ;                                     \
+        push    eax                   ;                                     \
+        mov     eax, param1           ;                                     \
+        push    eax                   ;                                     \
+        mov     ecx, this_            ;                                     \
+        mov     eax, [ecx]            ;                                     \
+        call    [eax+funcOffset]      ;                                     \
+        mov     resultName, eax       ;                                     \
+    }
+
+
+#elif defined(__GNUC__)
+
+
+#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )                  \
+    __asm__ __volatile__ ("movl (%1), %%edx\n\t"                            \
+                          "call *"#funcOffset"(%%edx)\n\t"                  \
+                          :"=a"(resultName) /* Output Operands */           \
+                          :"c"(thisPtr)     /* Input Operands */            \
+                          : "%edx" /* Clobbered Registers */                \
+                         );                                                 \
+
+
+#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )                 \
+    __asm__ __volatile__ ("pushl %0\n\t"                                    \
+                          "movl (%1), %%edx\n\t"                            \
+                          "call *"#funcOffset"(%%edx)\n\t"                  \
+                          :                 /* Output Operands */           \
+                          :"r"(param1),     /* Input Operands */            \
+                           "c"(thisPtr)                                     \
+                          : "%edx" /* Clobbered Registers */                \
+                         );                                                 \
+
+
+#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )          \
+    __asm__ __volatile__ ("pushl %1\n\t"                                    \
+                          "movl (%2), %%edx\n\t"                            \
+                          "call *"#funcOffset"(%%edx)\n\t"                  \
+                          :"=a"(resultName) /* Output Operands */           \
+                          :"r"(param1),     /* Input Operands */            \
+                           "c"(thisPtr)                                     \
+                          : "%edx" /* Clobbered Registers */                \
+                          );                                                \
+
+
+#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )   \
+    do {                                                                    \
+    double param1f64 = param1; /* Cast explicitly to double */              \
+    double *param1f64Ptr = &param1f64; /* Make pointer to address */        \
+     __asm__ __volatile__ ("pushl 4(%1)\n\t"                                \
+                           "pushl (%1)\n\t"                                 \
+                           "movl (%2), %%edx\n\t"                           \
+                           "call *"#funcOffset"(%%edx);\n\t"                \
+                           : "=a"(resultName) /* Output Operands */         \
+                           : "r"(param1f64Ptr),  /* Input Operands */       \
+                           "c"(thisPtr),                                    \
+                           "m"(*param1f64Ptr) /* Using address */           \
+                           : "%edx" /* Clobbered Registers */               \
+                           );                                               \
+    } while (0);                                                            \
+
+
+#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )  \
+    __asm__ __volatile__ ("pushl %1\n\t"                                    \
+                          "pushl %2\n\t"                                    \
+                          "movl (%3), %%edx\n\t"                            \
+                          "call *"#funcOffset"(%%edx)\n\t"                  \
+                          :"=a"(resultName) /* Output Operands */           \
+                          :"r"(param2),     /* Input Operands */            \
+                           "r"(param1),                                     \
+                           "c"(thisPtr)                                     \
+                          : "%edx" /* Clobbered Registers */                \
+                          );                                                \
+
+
+#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
+    __asm__ __volatile__ ("pushl %1\n\t"                                    \
+                          "pushl %2\n\t"                                    \
+                          "pushl %3\n\t"                                    \
+                          "pushl %4\n\t"                                    \
+                          "movl (%5), %%edx\n\t"                            \
+                          "call *"#funcOffset"(%%edx)\n\t"                  \
+                          :"=a"(resultName) /* Output Operands */           \
+                          :"r"(param4),     /* Input Operands  */           \
+                           "r"(param3),                                     \
+                           "r"(param2),                                     \
+                           "r"(param1),                                     \
+                           "c"(thisPtr)                                     \
+                          : "%edx" /* Clobbered Registers */                \
+                          );                                                \
+
+#endif
+
+
+
+// Our static singleton instance.
+IASIOThiscallResolver IASIOThiscallResolver::instance;
+
+// Constructor called to initialize static Singleton instance above. Note that
+// it is important not to clear that_ incase it has already been set by the call
+// to placement new in ASIOInit().
+IASIOThiscallResolver::IASIOThiscallResolver()
+{
+}
+
+// Constructor called from ASIOInit() below
+IASIOThiscallResolver::IASIOThiscallResolver(IASIO* that)
+: that_( that )
+{
+}
+
+// Implement IUnknown methods as assert(false). IASIOThiscallResolver is not
+// really a COM object, just a wrapper which will work with the ASIO SDK.
+// If you wanted to use ASIO without the SDK you might want to implement COM
+// aggregation in these methods.
+HRESULT STDMETHODCALLTYPE IASIOThiscallResolver::QueryInterface(REFIID riid, void **ppv)
+{
+    (void)riid;     // suppress unused variable warning
+
+    assert( false ); // this function should never be called by the ASIO SDK.
+
+    *ppv = NULL;
+    return E_NOINTERFACE;
+}
+
+ULONG STDMETHODCALLTYPE IASIOThiscallResolver::AddRef()
+{
+    assert( false ); // this function should never be called by the ASIO SDK.
+
+    return 1;
+}
+
+ULONG STDMETHODCALLTYPE IASIOThiscallResolver::Release()
+{
+    assert( false ); // this function should never be called by the ASIO SDK.
+    
+    return 1;
+}
+
+
+// Implement the IASIO interface methods by performing the vptr manipulation
+// described above then delegating to the real implementation.
+ASIOBool IASIOThiscallResolver::init(void *sysHandle)
+{
+    ASIOBool result;
+    CALL_THISCALL_1( result, that_, 12, sysHandle );
+    return result;
+}
+
+void IASIOThiscallResolver::getDriverName(char *name)
+{
+    CALL_VOID_THISCALL_1( that_, 16, name );
+}
+
+long IASIOThiscallResolver::getDriverVersion()
+{
+    ASIOBool result;
+    CALL_THISCALL_0( result, that_, 20 );
+    return result;
+}
+
+void IASIOThiscallResolver::getErrorMessage(char *string)
+{
+     CALL_VOID_THISCALL_1( that_, 24, string );
+}
+
+ASIOError IASIOThiscallResolver::start()
+{
+    ASIOBool result;
+    CALL_THISCALL_0( result, that_, 28 );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::stop()
+{
+    ASIOBool result;
+    CALL_THISCALL_0( result, that_, 32 );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::getChannels(long *numInputChannels, long *numOutputChannels)
+{
+    ASIOBool result;
+    CALL_THISCALL_2( result, that_, 36, numInputChannels, numOutputChannels );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::getLatencies(long *inputLatency, long *outputLatency)
+{
+    ASIOBool result;
+    CALL_THISCALL_2( result, that_, 40, inputLatency, outputLatency );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::getBufferSize(long *minSize, long *maxSize,
+        long *preferredSize, long *granularity)
+{
+    ASIOBool result;
+    CALL_THISCALL_4( result, that_, 44, minSize, maxSize, preferredSize, granularity );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::canSampleRate(ASIOSampleRate sampleRate)
+{
+    ASIOBool result;
+    CALL_THISCALL_1_DOUBLE( result, that_, 48, sampleRate );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::getSampleRate(ASIOSampleRate *sampleRate)
+{
+    ASIOBool result;
+    CALL_THISCALL_1( result, that_, 52, sampleRate );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::setSampleRate(ASIOSampleRate sampleRate)
+{    
+    ASIOBool result;
+    CALL_THISCALL_1_DOUBLE( result, that_, 56, sampleRate );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::getClockSources(ASIOClockSource *clocks, long *numSources)
+{
+    ASIOBool result;
+    CALL_THISCALL_2( result, that_, 60, clocks, numSources );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::setClockSource(long reference)
+{
+    ASIOBool result;
+    CALL_THISCALL_1( result, that_, 64, reference );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
+{
+    ASIOBool result;
+    CALL_THISCALL_2( result, that_, 68, sPos, tStamp );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::getChannelInfo(ASIOChannelInfo *info)
+{
+    ASIOBool result;
+    CALL_THISCALL_1( result, that_, 72, info );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::createBuffers(ASIOBufferInfo *bufferInfos,
+        long numChannels, long bufferSize, ASIOCallbacks *callbacks)
+{
+    ASIOBool result;
+    CALL_THISCALL_4( result, that_, 76, bufferInfos, numChannels, bufferSize, callbacks );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::disposeBuffers()
+{
+    ASIOBool result;
+    CALL_THISCALL_0( result, that_, 80 );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::controlPanel()
+{
+    ASIOBool result;
+    CALL_THISCALL_0( result, that_, 84 );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::future(long selector,void *opt)
+{
+    ASIOBool result;
+    CALL_THISCALL_2( result, that_, 88, selector, opt );
+    return result;
+}
+
+ASIOError IASIOThiscallResolver::outputReady()
+{
+    ASIOBool result;
+    CALL_THISCALL_0( result, that_, 92 );
+    return result;
+}
+
+
+// Implement our substitute ASIOInit() method
+ASIOError IASIOThiscallResolver::ASIOInit(ASIODriverInfo *info)
+{
+    // To ensure that our instance's vptr is correctly constructed, even if
+    // ASIOInit is called prior to main(), we explicitly call its constructor
+    // (potentially over the top of an existing instance). Note that this is
+    // pretty ugly, and is only safe because IASIOThiscallResolver has no
+    // destructor and contains no objects with destructors.
+    new((void*)&instance) IASIOThiscallResolver( theAsioDriver );
+
+    // Interpose between ASIO client code and the real driver.
+    theAsioDriver = &instance;
+
+    // Note that we never need to switch theAsioDriver back to point to the
+    // real driver because theAsioDriver is reset to zero in ASIOExit().
+
+    // Delegate to the real ASIOInit
+       return ::ASIOInit(info);
+}
+
+
+#endif /* !defined(_MSC_VER) */
+
+#endif /* Win32 */
+
index b59d910898741403b444886f066eb3824d1cf934..63e91ca319b1fc3b0dd1ef3b35145dc693250476 100644 (file)
 // We only need IASIOThiscallResolver at all if we are on Win32. For other\r
 // platforms we simply bypass the IASIOThiscallResolver definition to allow us\r
 // to be safely #include'd whatever the platform to keep client code portable\r
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)\r
+//#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)\r
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)\r
 \r
 \r
 // If microsoft compiler we can call IASIO directly so IASIOThiscallResolver\r
index 694767641993a6e2c94e897da297708713fc4c7f..0236fbe3fa06a0233a6f306a98ad17550dbcc77d 100644 (file)
@@ -49,7 +49,7 @@ clean :
        $(RM) -fR *.dSYM
 
 distclean: clean
-       $(RM) Makefile
+       $(RM) -f Makefile
 
 strip : 
        strip $(PROGRAMS)
index 125b56e2d12c827a0b04e3bbb0ee931254319ec7..938a7f87c08af96abac3ee382f5fc4de6d913c30 100644 (file)
@@ -53,7 +53,7 @@ int inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
   // a simple buffer copy operation here.
   if ( status ) std::cout << "Stream over/underflow detected." << std::endl;
 
-  unsigned long *bytes = (unsigned long *) data;
+  unsigned int *bytes = (unsigned int *) data;
   memcpy( outputBuffer, inputBuffer, *bytes );
   return 0;
 }
index 5a5e7cd07c387078d5fe54e0f8940d73c16265d8..3b7be76bbdaebdffff9e850e3a7e6cf4923118c7 100644 (file)
@@ -26,11 +26,7 @@ typedef signed short  MY_TYPE;
 #define SCALE  32767.0
 
 /*
-typedef signed long  MY_TYPE;
-#define FORMAT RTAUDIO_SINT24
-#define SCALE  8388607.0
-
-typedef signed long  MY_TYPE;
+typedef signed int  MY_TYPE;
 #define FORMAT RTAUDIO_SINT32
 #define SCALE  2147483647.0