gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

iasiothiscallresolver.h (9384B)


      1 // ****************************************************************************
      2 // File:			IASIOThiscallResolver.h
      3 // Description:     The IASIOThiscallResolver class implements the IASIO
      4 //					interface and acts as a proxy to the real IASIO interface by
      5 //                  calling through its vptr table using the thiscall calling
      6 //                  convention. To put it another way, we interpose
      7 //                  IASIOThiscallResolver between ASIO SDK code and the driver.
      8 //                  This is necessary because most non-Microsoft compilers don't
      9 //                  implement the thiscall calling convention used by IASIO.
     10 //
     11 //					iasiothiscallresolver.cpp contains the background of this
     12 //					problem plus a technical description of the vptr
     13 //                  manipulations.
     14 //
     15 //					In order to use this mechanism one simply has to add
     16 //					iasiothiscallresolver.cpp to the list of files to compile
     17 //                  and #include <iasiothiscallresolver.h>
     18 //
     19 //					Note that this #include must come after the other ASIO SDK
     20 //                  #includes, for example:
     21 //
     22 //					#include <windows.h>
     23 //					#include <asiosys.h>
     24 //					#include <asio.h>
     25 //					#include <asiodrivers.h>
     26 //					#include <iasiothiscallresolver.h>
     27 //
     28 //					Actually the important thing is to #include
     29 //                  <iasiothiscallresolver.h> after <asio.h>. We have
     30 //                  incorporated a test to enforce this ordering.
     31 //
     32 //					The code transparently takes care of the interposition by
     33 //                  using macro substitution to intercept calls to ASIOInit()
     34 //                  and ASIOExit(). We save the original ASIO global
     35 //                  "theAsioDriver" in our "that" variable, and then set
     36 //                  "theAsioDriver" to equal our IASIOThiscallResolver instance.
     37 //
     38 // 					Whilst this method of resolving the thiscall problem requires
     39 //					the addition of #include <iasiothiscallresolver.h> to client
     40 //                  code it has the advantage that it does not break the terms
     41 //                  of the ASIO licence by publishing it. We are NOT modifying
     42 //                  any Steinberg code here, we are merely implementing the IASIO
     43 //					interface in the same way that we would need to do if we
     44 //					wished to provide an open source ASIO driver.
     45 //
     46 //					For compilation with MinGW -lole32 needs to be added to the
     47 //                  linker options. For BORLAND, linking with Import32.lib is
     48 //                  sufficient.
     49 //
     50 //					The dependencies are with: CoInitialize, CoUninitialize,
     51 //					CoCreateInstance, CLSIDFromString - used by asiolist.cpp
     52 //					and are required on Windows whether ThiscallResolver is used
     53 //					or not.
     54 //
     55 //					Searching for the above strings in the root library path
     56 //					of your compiler should enable the correct libraries to be
     57 //					identified if they aren't immediately obvious.
     58 //
     59 //                  Note that the current implementation of IASIOThiscallResolver
     60 //                  is not COM compliant - it does not correctly implement the
     61 //                  IUnknown interface. Implementing it is not necessary because
     62 //                  it is not called by parts of the ASIO SDK which call through
     63 //                  theAsioDriver ptr. The IUnknown methods are implemented as
     64 //                  assert(false) to ensure that the code fails if they are
     65 //                  ever called.
     66 // Restrictions:	None. Public Domain & Open Source distribute freely
     67 //					You may use IASIOThiscallResolver commercially as well as
     68 //                  privately.
     69 //					You the user assume the responsibility for the use of the
     70 //					files, binary or text, and there is no guarantee or warranty,
     71 //					expressed or implied, including but not limited to the
     72 //					implied warranties of merchantability and fitness for a
     73 //					particular purpose. You assume all responsibility and agree
     74 //					to hold no entity, copyright holder or distributors liable
     75 //					for any loss of data or inaccurate representations of data
     76 //					as a result of using IASIOThiscallResolver.
     77 // Version:         1.4 Added separate macro CALL_THISCALL_1_DOUBLE from
     78 //                  Andrew Baldwin, and volatile for whole gcc asm blocks,
     79 //                  both for compatibility with newer gcc versions. Cleaned up
     80 //                  Borland asm to use one less register.
     81 //                  1.3 Switched to including assert.h for better compatibility.
     82 //                  Wrapped entire .h and .cpp contents with a check for
     83 //                  _MSC_VER to provide better compatibility with MS compilers.
     84 //                  Changed Singleton implementation to use static instance
     85 //                  instead of freestore allocated instance. Removed ASIOExit
     86 //                  macro as it is no longer needed.
     87 //                  1.2 Removed semicolons from ASIOInit and ASIOExit macros to
     88 //                  allow them to be embedded in expressions (if statements).
     89 //                  Cleaned up some comments. Removed combase.c dependency (it
     90 //                  doesn't compile with BCB anyway) by stubbing IUnknown.
     91 //                  1.1 Incorporated comments from Ross Bencina including things
     92 //					such as changing name from ThiscallResolver to
     93 //					IASIOThiscallResolver, tidying up the constructor, fixing
     94 //					a bug in IASIOThiscallResolver::ASIOExit() and improving
     95 //					portability through the use of conditional compilation
     96 //					1.0 Initial working version.
     97 // Created:			6/09/2003
     98 // Authors:         Fraser Adams
     99 //                  Ross Bencina
    100 //                  Rene G. Ceballos
    101 //                  Martin Fay
    102 //                  Antti Silvast
    103 //                  Andrew Baldwin
    104 //
    105 // ****************************************************************************
    106 
    107 
    108 #ifndef included_iasiothiscallresolver_h
    109 #define included_iasiothiscallresolver_h
    110 
    111 // We only need IASIOThiscallResolver at all if we are on Win32. For other
    112 // platforms we simply bypass the IASIOThiscallResolver definition to allow us
    113 // to be safely #include'd whatever the platform to keep client code portable
    114 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)
    115 
    116 
    117 // If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
    118 // is not used.
    119 #if !defined(_MSC_VER)
    120 
    121 
    122 // The following is in order to ensure that this header is only included after
    123 // the other ASIO headers (except for the case of iasiothiscallresolver.cpp).
    124 // We need to do this because IASIOThiscallResolver works by eclipsing the
    125 // original definition of ASIOInit() with a macro (see below).
    126 #if !defined(iasiothiscallresolver_sourcefile)
    127 	#if !defined(__ASIO_H)
    128 	#error iasiothiscallresolver.h must be included AFTER asio.h
    129 	#endif
    130 #endif
    131 
    132 #include <windows.h>
    133 #include <asiodrvr.h> /* From ASIO SDK */
    134 
    135 
    136 class IASIOThiscallResolver : public IASIO {
    137 private:
    138 	IASIO* that_; // Points to the real IASIO
    139 
    140 	static IASIOThiscallResolver instance; // Singleton instance
    141 
    142 	// Constructors - declared private so construction is limited to
    143     // our Singleton instance
    144     IASIOThiscallResolver();
    145 	IASIOThiscallResolver(IASIO* that);
    146 public:
    147 
    148     // Methods from the IUnknown interface. We don't fully implement IUnknown
    149     // because the ASIO SDK never calls these methods through theAsioDriver ptr.
    150     // These methods are implemented as assert(false).
    151     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
    152     virtual ULONG STDMETHODCALLTYPE AddRef();
    153     virtual ULONG STDMETHODCALLTYPE Release();
    154 
    155     // Methods from the IASIO interface, implemented as forwarning calls to that.
    156 	virtual ASIOBool init(void *sysHandle);
    157 	virtual void getDriverName(char *name);
    158 	virtual long getDriverVersion();
    159 	virtual void getErrorMessage(char *string);
    160 	virtual ASIOError start();
    161 	virtual ASIOError stop();
    162 	virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
    163 	virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
    164 	virtual ASIOError getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
    165 	virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
    166 	virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
    167 	virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
    168 	virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
    169 	virtual ASIOError setClockSource(long reference);
    170 	virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
    171 	virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
    172 	virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, long bufferSize, ASIOCallbacks *callbacks);
    173 	virtual ASIOError disposeBuffers();
    174 	virtual ASIOError controlPanel();
    175 	virtual ASIOError future(long selector,void *opt);
    176 	virtual ASIOError outputReady();
    177 
    178     // Class method, see ASIOInit() macro below.
    179     static ASIOError ASIOInit(ASIODriverInfo *info); // Delegates to ::ASIOInit
    180 };
    181 
    182 
    183 // Replace calls to ASIOInit with our interposing version.
    184 // This macro enables us to perform thiscall resolution simply by #including
    185 // <iasiothiscallresolver.h> after the asio #includes (this file _must_ be
    186 // included _after_ the asio #includes)
    187 
    188 #define ASIOInit(name) IASIOThiscallResolver::ASIOInit((name))
    189 
    190 
    191 #endif /* !defined(_MSC_VER) */
    192 
    193 #endif /* Win32 */
    194 
    195 #endif /* included_iasiothiscallresolver_h */
    196 
    197