iasiothiscallresolver.h

Go to the documentation of this file.
00001 // ****************************************************************************
00002 // File:                        IASIOThiscallResolver.h
00003 // Description:     The IASIOThiscallResolver class implements the IASIO
00004 //                                      interface and acts as a proxy to the real IASIO interface by
00005 //                  calling through its vptr table using the thiscall calling
00006 //                  convention. To put it another way, we interpose
00007 //                  IASIOThiscallResolver between ASIO SDK code and the driver.
00008 //                  This is necessary because most non-Microsoft compilers don't
00009 //                  implement the thiscall calling convention used by IASIO.
00010 //
00011 //                                      iasiothiscallresolver.cpp contains the background of this
00012 //                                      problem plus a technical description of the vptr
00013 //                  manipulations.
00014 //
00015 //                                      In order to use this mechanism one simply has to add
00016 //                                      iasiothiscallresolver.cpp to the list of files to compile
00017 //                  and #include <iasiothiscallresolver.h>
00018 //
00019 //                                      Note that this #include must come after the other ASIO SDK
00020 //                  #includes, for example:
00021 //
00022 //                                      #include <windows.h>
00023 //                                      #include <asiosys.h>
00024 //                                      #include <asio.h>
00025 //                                      #include <asiodrivers.h>
00026 //                                      #include <iasiothiscallresolver.h>
00027 //
00028 //                                      Actually the important thing is to #include
00029 //                  <iasiothiscallresolver.h> after <asio.h>. We have
00030 //                  incorporated a test to enforce this ordering.
00031 //
00032 //                                      The code transparently takes care of the interposition by
00033 //                  using macro substitution to intercept calls to ASIOInit()
00034 //                  and ASIOExit(). We save the original ASIO global
00035 //                  "theAsioDriver" in our "that" variable, and then set
00036 //                  "theAsioDriver" to equal our IASIOThiscallResolver instance.
00037 //
00038 //                                      Whilst this method of resolving the thiscall problem requires
00039 //                                      the addition of #include <iasiothiscallresolver.h> to client
00040 //                  code it has the advantage that it does not break the terms
00041 //                  of the ASIO licence by publishing it. We are NOT modifying
00042 //                  any Steinberg code here, we are merely implementing the IASIO
00043 //                                      interface in the same way that we would need to do if we
00044 //                                      wished to provide an open source ASIO driver.
00045 //
00046 //                                      For compilation with MinGW -lole32 needs to be added to the
00047 //                  linker options. For BORLAND, linking with Import32.lib is
00048 //                  sufficient.
00049 //
00050 //                                      The dependencies are with: CoInitialize, CoUninitialize,
00051 //                                      CoCreateInstance, CLSIDFromString - used by asiolist.cpp
00052 //                                      and are required on Windows whether ThiscallResolver is used
00053 //                                      or not.
00054 //
00055 //                                      Searching for the above strings in the root library path
00056 //                                      of your compiler should enable the correct libraries to be
00057 //                                      identified if they aren't immediately obvious.
00058 //
00059 //                  Note that the current implementation of IASIOThiscallResolver
00060 //                  is not COM compliant - it does not correctly implement the
00061 //                  IUnknown interface. Implementing it is not necessary because
00062 //                  it is not called by parts of the ASIO SDK which call through
00063 //                  theAsioDriver ptr. The IUnknown methods are implemented as
00064 //                  assert(false) to ensure that the code fails if they are
00065 //                  ever called.
00066 // Restrictions:        None. Public Domain & Open Source distribute freely
00067 //                                      You may use IASIOThiscallResolver commercially as well as
00068 //                  privately.
00069 //                                      You the user assume the responsibility for the use of the
00070 //                                      files, binary or text, and there is no guarantee or warranty,
00071 //                                      expressed or implied, including but not limited to the
00072 //                                      implied warranties of merchantability and fitness for a
00073 //                                      particular purpose. You assume all responsibility and agree
00074 //                                      to hold no entity, copyright holder or distributors liable
00075 //                                      for any loss of data or inaccurate representations of data
00076 //                                      as a result of using IASIOThiscallResolver.
00077 // Version:         1.4 Added separate macro CALL_THISCALL_1_DOUBLE from
00078 //                  Andrew Baldwin, and volatile for whole gcc asm blocks,
00079 //                  both for compatibility with newer gcc versions. Cleaned up
00080 //                  Borland asm to use one less register.
00081 //                  1.3 Switched to including assert.h for better compatibility.
00082 //                  Wrapped entire .h and .cpp contents with a check for
00083 //                  _MSC_VER to provide better compatibility with MS compilers.
00084 //                  Changed Singleton implementation to use static instance
00085 //                  instead of freestore allocated instance. Removed ASIOExit
00086 //                  macro as it is no longer needed.
00087 //                  1.2 Removed semicolons from ASIOInit and ASIOExit macros to
00088 //                  allow them to be embedded in expressions (if statements).
00089 //                  Cleaned up some comments. Removed combase.c dependency (it
00090 //                  doesn't compile with BCB anyway) by stubbing IUnknown.
00091 //                  1.1 Incorporated comments from Ross Bencina including things
00092 //                                      such as changing name from ThiscallResolver to
00093 //                                      IASIOThiscallResolver, tidying up the constructor, fixing
00094 //                                      a bug in IASIOThiscallResolver::ASIOExit() and improving
00095 //                                      portability through the use of conditional compilation
00096 //                                      1.0 Initial working version.
00097 // Created:                     6/09/2003
00098 // Authors:         Fraser Adams
00099 //                  Ross Bencina
00100 //                  Rene G. Ceballos
00101 //                  Martin Fay
00102 //                  Antti Silvast
00103 //                  Andrew Baldwin
00104 //
00105 // ****************************************************************************
00106 
00107 
00108 #ifndef included_iasiothiscallresolver_h
00109 #define included_iasiothiscallresolver_h
00110 
00111 // We only need IASIOThiscallResolver at all if we are on Win32. For other
00112 // platforms we simply bypass the IASIOThiscallResolver definition to allow us
00113 // to be safely #include'd whatever the platform to keep client code portable
00114 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
00115 
00116 
00117 // If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
00118 // is not used.
00119 #if !defined(_MSC_VER)
00120 
00121 
00122 // The following is in order to ensure that this header is only included after
00123 // the other ASIO headers (except for the case of iasiothiscallresolver.cpp).
00124 // We need to do this because IASIOThiscallResolver works by eclipsing the
00125 // original definition of ASIOInit() with a macro (see below).
00126 #if !defined(iasiothiscallresolver_sourcefile)
00127         #if !defined(__ASIO_H)
00128         #error iasiothiscallresolver.h must be included AFTER asio.h
00129         #endif
00130 #endif
00131 
00132 #include <windows.h>
00133 #include <asiodrvr.h> /* From ASIO SDK */
00134 
00135 
00136 class IASIOThiscallResolver : public IASIO {
00137 private:
00138         IASIO* that_; // Points to the real IASIO
00139 
00140         static IASIOThiscallResolver instance; // Singleton instance
00141 
00142         // Constructors - declared private so construction is limited to
00143     // our Singleton instance
00144     IASIOThiscallResolver();
00145         IASIOThiscallResolver(IASIO* that);
00146 public:
00147 
00148     // Methods from the IUnknown interface. We don't fully implement IUnknown
00149     // because the ASIO SDK never calls these methods through theAsioDriver ptr.
00150     // These methods are implemented as assert(false).
00151     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
00152     virtual ULONG STDMETHODCALLTYPE AddRef();
00153     virtual ULONG STDMETHODCALLTYPE Release();
00154 
00155     // Methods from the IASIO interface, implemented as forwarning calls to that.
00156         virtual ASIOBool init(void *sysHandle);
00157         virtual void getDriverName(char *name);
00158         virtual long getDriverVersion();
00159         virtual void getErrorMessage(char *string);
00160         virtual ASIOError start();
00161         virtual ASIOError stop();
00162         virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
00163         virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
00164         virtual ASIOError getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
00165         virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
00166         virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
00167         virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
00168         virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
00169         virtual ASIOError setClockSource(long reference);
00170         virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
00171         virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
00172         virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, long bufferSize, ASIOCallbacks *callbacks);
00173         virtual ASIOError disposeBuffers();
00174         virtual ASIOError controlPanel();
00175         virtual ASIOError future(long selector,void *opt);
00176         virtual ASIOError outputReady();
00177 
00178     // Class method, see ASIOInit() macro below.
00179     static ASIOError ASIOInit(ASIODriverInfo *info); // Delegates to ::ASIOInit
00180 };
00181 
00182 
00183 // Replace calls to ASIOInit with our interposing version.
00184 // This macro enables us to perform thiscall resolution simply by #including
00185 // <iasiothiscallresolver.h> after the asio #includes (this file _must_ be
00186 // included _after_ the asio #includes)
00187 
00188 #define ASIOInit(name) IASIOThiscallResolver::ASIOInit((name))
00189 
00190 
00191 #endif /* !defined(_MSC_VER) */
00192 
00193 #endif /* Win32 */
00194 
00195 #endif /* included_iasiothiscallresolver_h */
00196 
00197 

Generated on Sun Feb 3 05:57:02 2008 for PortAudio by  doxygen 1.5.4