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.

476 lines
12KB

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