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.cpp 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. //-----------------------------------------------------------------------------
  2. // Project : SDK Core
  3. //
  4. // Category : SDK Core Interfaces
  5. // Filename : pluginterfaces/base/funknown.cpp
  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. #include "funknown.h"
  17. #include "fstrdefs.h"
  18. #include <cstdio>
  19. #if SMTG_OS_WINDOWS
  20. #include <objbase.h>
  21. #endif
  22. #if SMTG_OS_MACOS
  23. #include <CoreFoundation/CoreFoundation.h>
  24. #if !defined (SMTG_USE_STDATOMIC_H)
  25. #if defined(MAC_OS_X_VERSION_10_11) && defined(MAC_OS_X_VERSION_MIN_REQUIRED)
  26. #define SMTG_USE_STDATOMIC_H (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_11)
  27. #else
  28. #define SMTG_USE_STDATOMIC_H 0
  29. #endif
  30. #endif // !defined (SMTG_USE_STDATOMIC_H)
  31. #if !SMTG_USE_STDATOMIC_H
  32. #include <libkern/OSAtomic.h>
  33. #if defined(__GNUC__) && (__GNUC__ >= 4) && !__LP64__
  34. // on 32 bit Mac OS X we can safely ignore the format warnings as sizeof(int) == sizeof(long)
  35. #pragma GCC diagnostic ignored "-Wformat"
  36. #endif
  37. #endif // !SMTG_USE_STDATOMIC_H
  38. #endif // SMTG_OS_MACOS
  39. #if SMTG_OS_LINUX
  40. #if !defined (SMTG_USE_STDATOMIC_H)
  41. #if defined (__ANDROID__) || defined(_LIBCPP_VERSION)
  42. #define SMTG_USE_STDATOMIC_H 1
  43. #else
  44. #include <ext/atomicity.h>
  45. #endif
  46. #endif // !defined (SMTG_USE_STDATOMIC_H)
  47. #include <stdlib.h>
  48. #endif
  49. #if defined (SMTG_USE_STDATOMIC_H) && SMTG_USE_STDATOMIC_H
  50. #include <stdatomic.h>
  51. #endif
  52. namespace Steinberg {
  53. //------------------------------------------------------------------------
  54. #if COM_COMPATIBLE
  55. #if SMTG_OS_WINDOWS
  56. #define GuidStruct GUID
  57. #else
  58. struct GuidStruct
  59. {
  60. uint32 Data1;
  61. uint16 Data2;
  62. uint16 Data3;
  63. uint8 Data4[8];
  64. };
  65. #endif
  66. #endif
  67. static void toString8 (char8* string, const char* data, int32 i1, int32 i2);
  68. static void fromString8 (const char8* string, char* data, int32 i1, int32 i2);
  69. static uint32 makeLong (uint8 b1, uint8 b2, uint8 b3, uint8 b4);
  70. //------------------------------------------------------------------------
  71. // FUnknownPrivate
  72. //------------------------------------------------------------------------
  73. namespace FUnknownPrivate {
  74. //------------------------------------------------------------------------
  75. int32 PLUGIN_API atomicAdd (int32& var, int32 d)
  76. {
  77. #if SMTG_USE_STDATOMIC_H
  78. return atomic_fetch_add (reinterpret_cast<atomic_int_least32_t*> (&var), d) + d;
  79. #else
  80. #if SMTG_OS_WINDOWS
  81. #ifdef __MINGW32__
  82. return InterlockedExchangeAdd (reinterpret_cast<long volatile*>(&var), d) + d;
  83. #else
  84. return InterlockedExchangeAdd ((LONG*)&var, d) + d;
  85. #endif
  86. #elif SMTG_OS_MACOS
  87. return OSAtomicAdd32Barrier (d, (int32_t*)&var);
  88. #elif defined(__ANDROID__)
  89. return atomic_fetch_add ((atomic_int*)&var, d) + d;
  90. #elif SMTG_OS_LINUX
  91. __gnu_cxx::__atomic_add (&var, d);
  92. return var;
  93. #else
  94. #warning implement me!
  95. var += d;
  96. return var;
  97. #endif
  98. #endif
  99. }
  100. } // FUnknownPrivate
  101. //------------------------------------------------------------------------
  102. // FUID implementation
  103. //------------------------------------------------------------------------
  104. FUID::FUID ()
  105. {
  106. memset (data, 0, sizeof (TUID));
  107. }
  108. //------------------------------------------------------------------------
  109. FUID::FUID (uint32 l1, uint32 l2, uint32 l3, uint32 l4)
  110. {
  111. from4Int (l1, l2, l3, l4);
  112. }
  113. //------------------------------------------------------------------------
  114. FUID::FUID (const FUID& f)
  115. {
  116. memcpy (data, f.data, sizeof (TUID));
  117. }
  118. //------------------------------------------------------------------------
  119. #if SMTG_CPP11_STDLIBSUPPORT
  120. FUID::FUID (FUID&& other)
  121. {
  122. memcpy (data, other.data, sizeof (TUID));
  123. }
  124. FUID& FUID::operator= (FUID&& other)
  125. {
  126. memcpy (data, other.data, sizeof (TUID));
  127. return *this;
  128. }
  129. #endif
  130. //------------------------------------------------------------------------
  131. bool FUID::generate ()
  132. {
  133. #if SMTG_OS_WINDOWS
  134. #if defined(_M_ARM64) || defined(_M_ARM)
  135. //#warning implement me!
  136. return false;
  137. #else
  138. GUID guid;
  139. HRESULT hr = CoCreateGuid (&guid);
  140. switch (hr)
  141. {
  142. case RPC_S_OK: memcpy (data, (char*)&guid, sizeof (TUID)); return true;
  143. case (HRESULT)RPC_S_UUID_LOCAL_ONLY:
  144. default: return false;
  145. }
  146. #endif
  147. #elif SMTG_OS_MACOS
  148. CFUUIDRef uuid = CFUUIDCreate (kCFAllocatorDefault);
  149. if (uuid)
  150. {
  151. CFUUIDBytes bytes = CFUUIDGetUUIDBytes (uuid);
  152. memcpy (data, (char*)&bytes, sizeof (TUID));
  153. CFRelease (uuid);
  154. return true;
  155. }
  156. return false;
  157. #elif SMTG_OS_LINUX
  158. srand ((size_t)this);
  159. for (int32 i = 0; i < 16; i++)
  160. data[i] = static_cast<unsigned char>(rand ());
  161. return true;
  162. #else
  163. #warning implement me!
  164. return false;
  165. #endif
  166. }
  167. //------------------------------------------------------------------------
  168. bool FUID::isValid () const
  169. {
  170. TUID nulluid = {0};
  171. return memcmp (data, nulluid, sizeof (TUID)) != 0;
  172. }
  173. //------------------------------------------------------------------------
  174. FUID& FUID::operator= (const FUID& f)
  175. {
  176. memcpy (data, f.data, sizeof (TUID));
  177. return *this;
  178. }
  179. //------------------------------------------------------------------------
  180. void FUID::from4Int (uint32 l1, uint32 l2, uint32 l3, uint32 l4)
  181. {
  182. #if COM_COMPATIBLE
  183. data [0] = (char)((l1 & 0x000000FF) );
  184. data [1] = (char)((l1 & 0x0000FF00) >> 8);
  185. data [2] = (char)((l1 & 0x00FF0000) >> 16);
  186. data [3] = (char)((l1 & 0xFF000000) >> 24);
  187. data [4] = (char)((l2 & 0x00FF0000) >> 16);
  188. data [5] = (char)((l2 & 0xFF000000) >> 24);
  189. data [6] = (char)((l2 & 0x000000FF) );
  190. data [7] = (char)((l2 & 0x0000FF00) >> 8);
  191. data [8] = (char)((l3 & 0xFF000000) >> 24);
  192. data [9] = (char)((l3 & 0x00FF0000) >> 16);
  193. data [10] = (char)((l3 & 0x0000FF00) >> 8);
  194. data [11] = (char)((l3 & 0x000000FF) );
  195. data [12] = (char)((l4 & 0xFF000000) >> 24);
  196. data [13] = (char)((l4 & 0x00FF0000) >> 16);
  197. data [14] = (char)((l4 & 0x0000FF00) >> 8);
  198. data [15] = (char)((l4 & 0x000000FF) );
  199. #else
  200. data [0] = (char)((l1 & 0xFF000000) >> 24);
  201. data [1] = (char)((l1 & 0x00FF0000) >> 16);
  202. data [2] = (char)((l1 & 0x0000FF00) >> 8);
  203. data [3] = (char)((l1 & 0x000000FF) );
  204. data [4] = (char)((l2 & 0xFF000000) >> 24);
  205. data [5] = (char)((l2 & 0x00FF0000) >> 16);
  206. data [6] = (char)((l2 & 0x0000FF00) >> 8);
  207. data [7] = (char)((l2 & 0x000000FF) );
  208. data [8] = (char)((l3 & 0xFF000000) >> 24);
  209. data [9] = (char)((l3 & 0x00FF0000) >> 16);
  210. data [10] = (char)((l3 & 0x0000FF00) >> 8);
  211. data [11] = (char)((l3 & 0x000000FF) );
  212. data [12] = (char)((l4 & 0xFF000000) >> 24);
  213. data [13] = (char)((l4 & 0x00FF0000) >> 16);
  214. data [14] = (char)((l4 & 0x0000FF00) >> 8);
  215. data [15] = (char)((l4 & 0x000000FF) );
  216. #endif
  217. }
  218. //------------------------------------------------------------------------
  219. void FUID::to4Int (uint32& d1, uint32& d2, uint32& d3, uint32& d4) const
  220. {
  221. d1 = getLong1 ();
  222. d2 = getLong2 ();
  223. d3 = getLong3 ();
  224. d4 = getLong4 ();
  225. }
  226. //------------------------------------------------------------------------
  227. uint32 FUID::getLong1 () const
  228. {
  229. #if COM_COMPATIBLE
  230. return makeLong (data[3], data[2], data[1], data[0]);
  231. #else
  232. return makeLong (data[0], data[1], data[2], data[3]);
  233. #endif
  234. }
  235. //------------------------------------------------------------------------
  236. uint32 FUID::getLong2 () const
  237. {
  238. #if COM_COMPATIBLE
  239. return makeLong (data[5], data[4], data[7], data[6]);
  240. #else
  241. return makeLong (data[4], data[5], data[6], data[7]);
  242. #endif
  243. }
  244. //------------------------------------------------------------------------
  245. uint32 FUID::getLong3 () const
  246. {
  247. #if COM_COMPATIBLE
  248. return makeLong (data[8], data[9], data[10], data[11]);
  249. #else
  250. return makeLong (data[8], data[9], data[10], data[11]);
  251. #endif
  252. }
  253. //------------------------------------------------------------------------
  254. uint32 FUID::getLong4 () const
  255. {
  256. #if COM_COMPATIBLE
  257. return makeLong (data[12], data[13], data[14], data[15]);
  258. #else
  259. return makeLong (data[12], data[13], data[14], data[15]);
  260. #endif
  261. }
  262. //------------------------------------------------------------------------
  263. void FUID::toString (char8* string) const
  264. {
  265. if (!string)
  266. return;
  267. #if COM_COMPATIBLE
  268. auto* g = (GuidStruct*)data;
  269. char8 s[17];
  270. Steinberg::toString8 (s, data, 8, 16);
  271. sprintf (string, "%08X%04X%04X%s", g->Data1, g->Data2, g->Data3, s);
  272. #else
  273. Steinberg::toString8 (string, data, 0, 16);
  274. #endif
  275. }
  276. //------------------------------------------------------------------------
  277. bool FUID::fromString (const char8* string)
  278. {
  279. if (!string || !*string)
  280. return false;
  281. if (strlen (string) != 32)
  282. return false;
  283. #if COM_COMPATIBLE
  284. GuidStruct g;
  285. char s[33];
  286. strcpy (s, string);
  287. s[8] = 0;
  288. sscanf (s, "%x", &g.Data1);
  289. strcpy (s, string + 8);
  290. s[4] = 0;
  291. sscanf (s, "%hx", &g.Data2);
  292. strcpy (s, string + 12);
  293. s[4] = 0;
  294. sscanf (s, "%hx", &g.Data3);
  295. memcpy (data, &g, 8);
  296. Steinberg::fromString8 (string + 16, data, 8, 16);
  297. #else
  298. Steinberg::fromString8 (string, data, 0, 16);
  299. #endif
  300. return true;
  301. }
  302. //------------------------------------------------------------------------
  303. bool FUID::fromRegistryString (const char8* string)
  304. {
  305. if (!string || !*string)
  306. return false;
  307. if (strlen (string) != 38)
  308. return false;
  309. // e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef}
  310. #if COM_COMPATIBLE
  311. GuidStruct g;
  312. char8 s[10];
  313. strncpy (s, string + 1, 8);
  314. s[8] = 0;
  315. sscanf (s, "%x", &g.Data1);
  316. strncpy (s, string + 10, 4);
  317. s[4] = 0;
  318. sscanf (s, "%hx", &g.Data2);
  319. strncpy (s, string + 15, 4);
  320. s[4] = 0;
  321. sscanf (s, "%hx", &g.Data3);
  322. memcpy (data, &g, 8);
  323. Steinberg::fromString8 (string + 20, data, 8, 10);
  324. Steinberg::fromString8 (string + 25, data, 10, 16);
  325. #else
  326. Steinberg::fromString8 (string + 1, data, 0, 4);
  327. Steinberg::fromString8 (string + 10, data, 4, 6);
  328. Steinberg::fromString8 (string + 15, data, 6, 8);
  329. Steinberg::fromString8 (string + 20, data, 8, 10);
  330. Steinberg::fromString8 (string + 25, data, 10, 16);
  331. #endif
  332. return true;
  333. }
  334. //------------------------------------------------------------------------
  335. void FUID::toRegistryString (char8* string) const
  336. {
  337. // e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef}
  338. #if COM_COMPATIBLE
  339. auto* g = (GuidStruct*)data;
  340. char8 s1[5];
  341. Steinberg::toString8 (s1, data, 8, 10);
  342. char8 s2[13];
  343. Steinberg::toString8 (s2, data, 10, 16);
  344. sprintf (string, "{%08X-%04X-%04X-%s-%s}", g->Data1, g->Data2, g->Data3, s1, s2);
  345. #else
  346. char8 s1[9];
  347. Steinberg::toString8 (s1, data, 0, 4);
  348. char8 s2[5];
  349. Steinberg::toString8 (s2, data, 4, 6);
  350. char8 s3[5];
  351. Steinberg::toString8 (s3, data, 6, 8);
  352. char8 s4[5];
  353. Steinberg::toString8 (s4, data, 8, 10);
  354. char8 s5[13];
  355. Steinberg::toString8 (s5, data, 10, 16);
  356. sprintf (string, "{%s-%s-%s-%s-%s}", s1, s2, s3, s4, s5);
  357. #endif
  358. }
  359. //------------------------------------------------------------------------
  360. void FUID::print (char8* string, int32 style) const
  361. {
  362. if (!string) // no string: debug output
  363. {
  364. char8 str[128];
  365. print (str, style);
  366. #if SMTG_OS_WINDOWS
  367. OutputDebugStringA (str);
  368. OutputDebugStringA ("\n");
  369. #else
  370. fprintf (stdout, "%s\n", str);
  371. #endif
  372. return;
  373. }
  374. uint32 l1, l2, l3, l4;
  375. to4Int (l1, l2, l3, l4);
  376. switch (style)
  377. {
  378. case kINLINE_UID:
  379. sprintf (string, "INLINE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4);
  380. break;
  381. case kDECLARE_UID:
  382. sprintf (string, "DECLARE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4);
  383. break;
  384. case kFUID:
  385. sprintf (string, "FUID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4);
  386. break;
  387. case kCLASS_UID:
  388. default:
  389. sprintf (string, "DECLARE_CLASS_IID (Interface, 0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1,
  390. l2, l3, l4);
  391. break;
  392. }
  393. }
  394. //------------------------------------------------------------------------
  395. // helpers
  396. //------------------------------------------------------------------------
  397. static uint32 makeLong (uint8 b1, uint8 b2, uint8 b3, uint8 b4)
  398. {
  399. return (uint32 (b1) << 24) | (uint32 (b2) << 16) | (uint32 (b3) << 8) | uint32 (b4);
  400. }
  401. //------------------------------------------------------------------------
  402. static void toString8 (char8* string, const char* data, int32 i1, int32 i2)
  403. {
  404. *string = 0;
  405. for (int32 i = i1; i < i2; i++)
  406. {
  407. char8 s[3];
  408. sprintf (s, "%02X", (uint8)data[i]);
  409. strcat (string, s);
  410. }
  411. }
  412. //------------------------------------------------------------------------
  413. static void fromString8 (const char8* string, char* data, int32 i1, int32 i2)
  414. {
  415. for (int32 i = i1; i < i2; i++)
  416. {
  417. char8 s[3];
  418. s[0] = *string++;
  419. s[1] = *string++;
  420. s[2] = 0;
  421. int32 d = 0;
  422. sscanf (s, "%2x", &d);
  423. data[i] = (char)d;
  424. }
  425. }
  426. //------------------------------------------------------------------------
  427. } // namespace Steinberg