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.

456 lines
19KB

  1. //-----------------------------------------------------------------------------
  2. // Project : SDK Core
  3. //
  4. // Category : SDK Core Interfaces
  5. // Filename : pluginterfaces/base/funknown.h
  6. // Created by : Steinberg, 01/2004
  7. // Description : Basic Interface
  8. //
  9. //-----------------------------------------------------------------------------
  10. // This file is part of a Steinberg SDK. It is subject to the license terms
  11. // in the LICENSE file found in the top-level directory of this distribution
  12. // and at www.steinberg.net/sdklicenses.
  13. // No part of the SDK, including this file, may be copied, modified, propagated,
  14. // or distributed except according to the terms contained in the LICENSE file.
  15. //-----------------------------------------------------------------------------
  16. #pragma once
  17. #include "pluginterfaces/base/fplatform.h"
  18. #include "pluginterfaces/base/ftypes.h"
  19. #include "pluginterfaces/base/smartpointer.h"
  20. #include <string.h>
  21. //------------------------------------------------------------------------
  22. /*! \defgroup pluginBase Basic Interfaces
  23. */
  24. //------------------------------------------------------------------------
  25. //------------------------------------------------------------------------
  26. // Unique Identifier macros
  27. //------------------------------------------------------------------------
  28. #if COM_COMPATIBLE
  29. #define INLINE_UID(l1, l2, l3, l4) \
  30. { \
  31. (::Steinberg::int8)((l1 & 0x000000FF) ), (::Steinberg::int8)((l1 & 0x0000FF00) >> 8), \
  32. (::Steinberg::int8)((l1 & 0x00FF0000) >> 16), (::Steinberg::int8)((l1 & 0xFF000000) >> 24), \
  33. (::Steinberg::int8)((l2 & 0x00FF0000) >> 16), (::Steinberg::int8)((l2 & 0xFF000000) >> 24), \
  34. (::Steinberg::int8)((l2 & 0x000000FF) ), (::Steinberg::int8)((l2 & 0x0000FF00) >> 8), \
  35. (::Steinberg::int8)((l3 & 0xFF000000) >> 24), (::Steinberg::int8)((l3 & 0x00FF0000) >> 16), \
  36. (::Steinberg::int8)((l3 & 0x0000FF00) >> 8), (::Steinberg::int8)((l3 & 0x000000FF) ), \
  37. (::Steinberg::int8)((l4 & 0xFF000000) >> 24), (::Steinberg::int8)((l4 & 0x00FF0000) >> 16), \
  38. (::Steinberg::int8)((l4 & 0x0000FF00) >> 8), (::Steinberg::int8)((l4 & 0x000000FF) ) \
  39. }
  40. #else
  41. #define INLINE_UID(l1, l2, l3, l4) \
  42. { \
  43. (::Steinberg::int8)((l1 & 0xFF000000) >> 24), (::Steinberg::int8)((l1 & 0x00FF0000) >> 16), \
  44. (::Steinberg::int8)((l1 & 0x0000FF00) >> 8), (::Steinberg::int8)((l1 & 0x000000FF) ), \
  45. (::Steinberg::int8)((l2 & 0xFF000000) >> 24), (::Steinberg::int8)((l2 & 0x00FF0000) >> 16), \
  46. (::Steinberg::int8)((l2 & 0x0000FF00) >> 8), (::Steinberg::int8)((l2 & 0x000000FF) ), \
  47. (::Steinberg::int8)((l3 & 0xFF000000) >> 24), (::Steinberg::int8)((l3 & 0x00FF0000) >> 16), \
  48. (::Steinberg::int8)((l3 & 0x0000FF00) >> 8), (::Steinberg::int8)((l3 & 0x000000FF) ), \
  49. (::Steinberg::int8)((l4 & 0xFF000000) >> 24), (::Steinberg::int8)((l4 & 0x00FF0000) >> 16), \
  50. (::Steinberg::int8)((l4 & 0x0000FF00) >> 8), (::Steinberg::int8)((l4 & 0x000000FF) ) \
  51. }
  52. #endif
  53. //------------------------------------------------------------------------
  54. #define DECLARE_UID(name, l1, l2, l3, l4) \
  55. ::Steinberg::TUID name = INLINE_UID (l1, l2, l3, l4);
  56. //------------------------------------------------------------------------
  57. #define EXTERN_UID(name) \
  58. extern const ::Steinberg::TUID name;
  59. #ifdef INIT_CLASS_IID
  60. #define DECLARE_CLASS_IID(ClassName, l1, l2, l3, l4) static const ::Steinberg::TUID ClassName##_iid = INLINE_UID (l1, l2, l3, l4); \
  61. const ::Steinberg::FUID ClassName::iid (ClassName##_iid);
  62. #else
  63. #define DECLARE_CLASS_IID(ClassName, l1, l2, l3, l4) static const ::Steinberg::TUID ClassName##_iid = INLINE_UID (l1, l2, l3, l4);
  64. #endif
  65. #define DEF_CLASS_IID(ClassName) const ::Steinberg::FUID ClassName::iid (ClassName##_iid);
  66. #define INLINE_UID_OF(ClassName) ClassName##_iid
  67. #define INLINE_UID_FROM_FUID(x) INLINE_UID(x.getLong1 (), x.getLong2 (), x.getLong3 (), x.getLong4 ())
  68. //------------------------------------------------------------------------
  69. // FUnknown implementation macros
  70. //------------------------------------------------------------------------
  71. #define DECLARE_FUNKNOWN_METHODS \
  72. public: \
  73. virtual ::Steinberg::tresult PLUGIN_API queryInterface (const ::Steinberg::TUID _iid, void** obj) SMTG_OVERRIDE; \
  74. virtual ::Steinberg::uint32 PLUGIN_API addRef () SMTG_OVERRIDE; \
  75. virtual ::Steinberg::uint32 PLUGIN_API release () SMTG_OVERRIDE; \
  76. protected : \
  77. ::Steinberg::int32 __funknownRefCount; \
  78. public:
  79. //------------------------------------------------------------------------
  80. #define DELEGATE_REFCOUNT(ClassName) \
  81. public: \
  82. virtual ::Steinberg::uint32 PLUGIN_API addRef () SMTG_OVERRIDE { return ClassName::addRef (); } \
  83. virtual ::Steinberg::uint32 PLUGIN_API release () SMTG_OVERRIDE { return ClassName::release (); }
  84. //------------------------------------------------------------------------
  85. #define IMPLEMENT_REFCOUNT(ClassName) \
  86. ::Steinberg::uint32 PLUGIN_API ClassName::addRef () \
  87. { \
  88. return ::Steinberg::FUnknownPrivate::atomicAdd (__funknownRefCount, 1); \
  89. } \
  90. ::Steinberg::uint32 PLUGIN_API ClassName::release () \
  91. { \
  92. if (::Steinberg::FUnknownPrivate::atomicAdd (__funknownRefCount, -1) == 0) \
  93. { \
  94. delete this; \
  95. return 0; \
  96. } \
  97. return __funknownRefCount; \
  98. }
  99. //------------------------------------------------------------------------
  100. #define FUNKNOWN_CTOR { __funknownRefCount = 1; }
  101. #define FUNKNOWN_DTOR
  102. //------------------------------------------------------------------------
  103. #define QUERY_INTERFACE(iid, obj, InterfaceIID, InterfaceName) \
  104. if (::Steinberg::FUnknownPrivate::iidEqual (iid, InterfaceIID)) \
  105. { \
  106. addRef (); \
  107. *obj = static_cast< InterfaceName* >(this); \
  108. return ::Steinberg::kResultOk; \
  109. }
  110. //------------------------------------------------------------------------
  111. #define IMPLEMENT_QUERYINTERFACE(ClassName, InterfaceName, ClassIID) \
  112. ::Steinberg::tresult PLUGIN_API ClassName::queryInterface (const ::Steinberg::TUID _iid, void** obj) \
  113. { \
  114. QUERY_INTERFACE (_iid, obj, ::Steinberg::FUnknown::iid, InterfaceName) \
  115. QUERY_INTERFACE (_iid, obj, ClassIID, InterfaceName) \
  116. *obj = nullptr; \
  117. return ::Steinberg::kNoInterface; \
  118. }
  119. //------------------------------------------------------------------------
  120. #define IMPLEMENT_FUNKNOWN_METHODS(ClassName,InterfaceName,ClassIID) \
  121. IMPLEMENT_REFCOUNT (ClassName) \
  122. IMPLEMENT_QUERYINTERFACE (ClassName, InterfaceName, ClassIID)
  123. //------------------------------------------------------------------------
  124. // Result Codes
  125. //------------------------------------------------------------------------
  126. namespace Steinberg {
  127. //------------------------------------------------------------------------
  128. #if COM_COMPATIBLE
  129. #if WINDOWS
  130. enum
  131. {
  132. kNoInterface = static_cast<tresult>(0x80004002L), // E_NOINTERFACE
  133. kResultOk = static_cast<tresult>(0x00000000L), // S_OK
  134. kResultTrue = kResultOk,
  135. kResultFalse = static_cast<tresult>(0x00000001L), // S_FALSE
  136. kInvalidArgument = static_cast<tresult>(0x80070057L), // E_INVALIDARG
  137. kNotImplemented = static_cast<tresult>(0x80004001L), // E_NOTIMPL
  138. kInternalError = static_cast<tresult>(0x80004005L), // E_FAIL
  139. kNotInitialized = static_cast<tresult>(0x8000FFFFL), // E_UNEXPECTED
  140. kOutOfMemory = static_cast<tresult>(0x8007000EL) // E_OUTOFMEMORY
  141. };
  142. #else
  143. enum
  144. {
  145. kNoInterface = static_cast<tresult>(0x80000004L), // E_NOINTERFACE
  146. kResultOk = static_cast<tresult>(0x00000000L), // S_OK
  147. kResultTrue = kResultOk,
  148. kResultFalse = static_cast<tresult>(0x00000001L), // S_FALSE
  149. kInvalidArgument = static_cast<tresult>(0x80000003L), // E_INVALIDARG
  150. kNotImplemented = static_cast<tresult>(0x80000001L), // E_NOTIMPL
  151. kInternalError = static_cast<tresult>(0x80000008L), // E_FAIL
  152. kNotInitialized = static_cast<tresult>(0x8000FFFFL), // E_UNEXPECTED
  153. kOutOfMemory = static_cast<tresult>(0x80000002L) // E_OUTOFMEMORY
  154. };
  155. #endif
  156. #else
  157. enum
  158. {
  159. kNoInterface = -1,
  160. kResultOk,
  161. kResultTrue = kResultOk,
  162. kResultFalse,
  163. kInvalidArgument,
  164. kNotImplemented,
  165. kInternalError,
  166. kNotInitialized,
  167. kOutOfMemory
  168. };
  169. #endif
  170. //------------------------------------------------------------------------
  171. typedef int64 LARGE_INT; // obsolete
  172. //------------------------------------------------------------------------
  173. // FUID class declaration
  174. //------------------------------------------------------------------------
  175. typedef int8 TUID[16]; ///< plain UID type
  176. //------------------------------------------------------------------------
  177. /* FUnknown private */
  178. namespace FUnknownPrivate {
  179. SMTG_ALWAYS_INLINE bool iidEqual (const void* iid1, const void* iid2)
  180. {
  181. const uint64* p1 = reinterpret_cast<const uint64*> (iid1);
  182. const uint64* p2 = reinterpret_cast<const uint64*> (iid2);
  183. return p1[0] == p2[0] && p1[1] == p2[1];
  184. }
  185. int32 PLUGIN_API atomicAdd (int32& value, int32 amount);
  186. }
  187. //------------------------------------------------------------------------
  188. /** Handling 16 Byte Globaly Unique Identifiers.
  189. \ingroup pluginBase
  190. Each interface declares its identifier as static member inside the interface
  191. namespace (e.g. FUnknown::iid).
  192. */
  193. //------------------------------------------------------------------------
  194. class FUID
  195. {
  196. public:
  197. //------------------------------------------------------------------------
  198. FUID ();
  199. inline FUID (const TUID uid);
  200. FUID (uint32 l1, uint32 l2, uint32 l3, uint32 l4);
  201. FUID (const FUID&);
  202. virtual ~FUID () {}
  203. #if SMTG_CPP11_STDLIBSUPPORT
  204. FUID (FUID&& other);
  205. FUID& operator= (FUID&& other);
  206. #endif
  207. /** Generates a new Unique Identifier (UID).
  208. Will return true for success. If the return value is false, either no
  209. UID is generated or the UID is not guaranteed to be unique worldwide. */
  210. bool generate ();
  211. /** Checks if the UID data is valid.
  212. The default constructor initializes the memory with zeros. */
  213. bool isValid () const;
  214. FUID& operator = (const FUID& f);
  215. FUID& operator = (FIDString uid);
  216. FUID& operator = (TUID uid);
  217. bool operator == (const FUID& f) const { return ::Steinberg::FUnknownPrivate::iidEqual (data, f.data); }
  218. bool operator == (FIDString uid) const { return ::Steinberg::FUnknownPrivate::iidEqual (data, uid); }
  219. bool operator == (TUID uid) const { return ::Steinberg::FUnknownPrivate::iidEqual (data, uid); }
  220. bool operator < (const FUID& f) const { return memcmp (data, f.data, sizeof (TUID)) < 0; }
  221. bool operator < (FIDString uid) const { return memcmp (data, uid, sizeof (TUID)) < 0; }
  222. bool operator < (TUID uid) const { return memcmp (data, uid, sizeof (TUID)) < 0; }
  223. bool operator != (const FUID& f) const { return !::Steinberg::FUnknownPrivate::iidEqual (data, f.data); }
  224. bool operator != (FIDString uid) const { return !::Steinberg::FUnknownPrivate::iidEqual (data, uid); }
  225. bool operator != (TUID uid) const { return !::Steinberg::FUnknownPrivate::iidEqual (data, uid); }
  226. operator FIDString () const { return data; }
  227. operator char* () { return data; }
  228. uint32 getLong1 () const;
  229. uint32 getLong2 () const;
  230. uint32 getLong3 () const;
  231. uint32 getLong4 () const;
  232. void from4Int (uint32 d1, uint32 d2, uint32 d3, uint32 d4);
  233. void to4Int (uint32& d1, uint32& d2, uint32& d3, uint32& d4) const;
  234. typedef char8 String [64];
  235. /** Converts UID to a string.
  236. The string will be 32 characters long, representing the hexadecimal values
  237. of each data byte (e.g. "9127BE30160E4BB69966670AA6087880"). */
  238. void toString (char8* string) const;
  239. /** Sets the UID data from a string.
  240. The string has to be 32 characters long, where each character-pair is
  241. the ASCII-encoded hexadecimal value of the corresponding data byte. */
  242. bool fromString (const char8* string);
  243. /** Converts UID to a string in Microsoft® OLE format.
  244. (e.g. "{c200e360-38c5-11ce-ae62-08002b2b79ef}") */
  245. void toRegistryString (char8* string) const;
  246. /** Sets the UID data from a string in Microsoft® OLE format. */
  247. bool fromRegistryString (const char8* string);
  248. enum UIDPrintStyle
  249. {
  250. kINLINE_UID, ///< "INLINE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
  251. kDECLARE_UID, ///< "DECLARE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
  252. kFUID, ///< "FUID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
  253. kCLASS_UID ///< "DECLARE_CLASS_IID (Interface, 0x00000000, 0x00000000, 0x00000000, 0x00000000)"
  254. };
  255. /** Prints the UID to a string (or debug output if string is NULL).
  256. \param string is the output string if not NULL.
  257. \param style can be chosen from the FUID::UIDPrintStyle enumeration. */
  258. void print (char8* string = 0, int32 style = kINLINE_UID) const;
  259. void toTUID (TUID result) const;
  260. inline const TUID& toTUID () const
  261. {
  262. return data;
  263. }
  264. //------------------------------------------------------------------------
  265. protected:
  266. TUID data;
  267. };
  268. //------------------------------------------------------------------------
  269. inline FUID::FUID (const TUID uid)
  270. {
  271. memset (data, 0, sizeof (TUID));
  272. if (uid)
  273. memcpy (data, uid, sizeof (TUID));
  274. }
  275. //------------------------------------------------------------------------
  276. // FUnknown
  277. //------------------------------------------------------------------------
  278. /** The basic interface of all interfaces.
  279. \ingroup pluginBase
  280. - The FUnknown::queryInterface method is used to retrieve pointers to other
  281. interfaces of the object.
  282. - FUnknown::addRef and FUnknown::release manage the lifetime of the object.
  283. If no more references exist, the object is destroyed in memory.
  284. Interfaces are identified by 16 byte Globally Unique Identifiers.
  285. The SDK provides a class called FUID for this purpose.
  286. \ref howtoClass */
  287. //------------------------------------------------------------------------
  288. class FUnknown
  289. {
  290. public:
  291. //------------------------------------------------------------------------
  292. /** Query for a pointer to the specified interface.
  293. Returns kResultOk on success or kNoInterface if the object does not implement the interface.
  294. The object has to call addRef when returning an interface.
  295. \param _iid : (in) 16 Byte interface identifier (-> FUID)
  296. \param obj : (out) On return, *obj points to the requested interface */
  297. virtual tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) = 0;
  298. /** Adds a reference and return the new reference count.
  299. \par Remarks:
  300. The initial reference count after creating an object is 1. */
  301. virtual uint32 PLUGIN_API addRef () = 0;
  302. /** Releases a reference and return the new reference count.
  303. If the reference count reaches zero, the object will be destroyed in memory. */
  304. virtual uint32 PLUGIN_API release () = 0;
  305. //------------------------------------------------------------------------
  306. static const FUID iid;
  307. //------------------------------------------------------------------------
  308. };
  309. DECLARE_CLASS_IID (FUnknown, 0x00000000, 0x00000000, 0xC0000000, 0x00000046)
  310. //------------------------------------------------------------------------
  311. // FUnknownPtr
  312. //------------------------------------------------------------------------
  313. /** FUnknownPtr - automatic interface conversion and smart pointer in one.
  314. This template class can be used for interface conversion like this:
  315. \code
  316. IPtr<IPath> path = owned (FHostCreate (IPath, hostClasses));
  317. FUnknownPtr<IPath2> path2 (path); // does a query interface for IPath2
  318. if (path2)
  319. ...
  320. \endcode
  321. */
  322. //------------------------------------------------------------------------
  323. template <class I>
  324. class FUnknownPtr : public IPtr<I>
  325. {
  326. public:
  327. //------------------------------------------------------------------------
  328. inline FUnknownPtr (FUnknown* unknown); // query interface
  329. inline FUnknownPtr (const FUnknownPtr& p) : IPtr<I> (p) {}
  330. inline FUnknownPtr () {}
  331. inline FUnknownPtr& operator=(const FUnknownPtr& p) {IPtr<I>::operator=(p); return *this;}
  332. inline I* operator=(FUnknown* unknown);
  333. inline I* getInterface () { return this->ptr; }
  334. };
  335. //------------------------------------------------------------------------
  336. template <class I>
  337. inline FUnknownPtr<I>::FUnknownPtr (FUnknown* unknown)
  338. {
  339. if (unknown && unknown->queryInterface (I::iid, (void**)&this->ptr) != kResultOk)
  340. this->ptr = 0;
  341. }
  342. //------------------------------------------------------------------------
  343. template <class I>
  344. inline I* FUnknownPtr<I>::operator=(FUnknown* unknown)
  345. {
  346. I* newPtr = 0;
  347. if (unknown && unknown->queryInterface (I::iid, (void**)&newPtr) == kResultOk)
  348. {
  349. OPtr<I> rel (newPtr);
  350. return IPtr<I>::operator=(newPtr);
  351. }
  352. return IPtr<I>::operator=(0);
  353. }
  354. //------------------------------------------------------------------------
  355. // FReleaser (obsolete)
  356. //------------------------------------------------------------------------
  357. /** Release an interface using automatic object (obsolete).
  358. This class is obsolete and is only kept for compatibility.
  359. The replacement for FReleaser is OPtr.
  360. Usage example with FReleaser:
  361. \code
  362. void someFunction ()
  363. {
  364. IPath* path = pathCreateMethod ();
  365. FReleaser releaser (path);
  366. .... do something with path...
  367. .... path not used anymore, releaser will destroy it when leaving function scope
  368. }
  369. \endcode
  370. Usage example with OPtr:
  371. \code
  372. void someFunction ()
  373. {
  374. OPtr<IPath> path = pathCreateMethod ();
  375. .... do something with path...
  376. .... path not used anymore, OPtr will destroy it when leaving function scope
  377. }
  378. \endcode
  379. */
  380. //------------------------------------------------------------------------
  381. struct FReleaser
  382. {
  383. FReleaser (FUnknown* u): u (u) {}
  384. ~FReleaser () { if (u) u->release (); }
  385. FUnknown* u;
  386. };
  387. //------------------------------------------------------------------------
  388. } // namespace Steinberg