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.

funknown.h 19KB

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