Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
9.6KB

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