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.

457 lines
11KB

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