Collection of DPF-based plugins for packaging
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.

444 lines
11KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef DISTRHO_UTILS_HPP_INCLUDED
  17. #define DISTRHO_UTILS_HPP_INCLUDED
  18. #include "src/DistrhoDefines.h"
  19. #include <cstdarg>
  20. #include <cstdio>
  21. #include <cstdlib>
  22. #include <cstring>
  23. #include <cmath>
  24. #include <limits>
  25. #ifdef DISTRHO_PROPER_CPP11_SUPPORT
  26. # include <cstdint>
  27. #else
  28. # include <stdint.h>
  29. #endif
  30. #if defined(DISTRHO_OS_WINDOWS) && defined(_MSC_VER)
  31. #include <basetsd.h>
  32. typedef SSIZE_T ssize_t;
  33. #endif
  34. #if ! defined(CARLA_MATH_UTILS_HPP_INCLUDED) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) && ! defined(DISTRHO_OS_MAC)
  35. namespace std {
  36. inline float fmin(float __x, float __y)
  37. { return __builtin_fminf(__x, __y); }
  38. inline float fmax(float __x, float __y)
  39. { return __builtin_fmaxf(__x, __y); }
  40. inline float rint(float __x)
  41. { return __builtin_rintf(__x); }
  42. inline float round(float __x)
  43. { return __builtin_roundf(__x); }
  44. }
  45. #endif
  46. #ifndef M_PI
  47. # define M_PI 3.14159265358979323846
  48. #endif
  49. /* --------------------------------------------------------------------------------------------------------------------
  50. * misc functions */
  51. /**
  52. @defgroup MiscellaneousFunctions Miscellaneous functions
  53. @{
  54. */
  55. /**
  56. Return a 32-bit number from 4 8-bit numbers.@n
  57. The return type is a int64_t for better compatibility with plugin formats that use such numbers.
  58. */
  59. static inline constexpr
  60. int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) noexcept
  61. {
  62. return (a << 24) | (b << 16) | (c << 8) | (d << 0);
  63. }
  64. /**
  65. Return a 32-bit number from 4 ASCII characters.
  66. */
  67. static inline constexpr
  68. uint32_t d_cconst(const char str[4])
  69. {
  70. return (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3];
  71. }
  72. /**
  73. Return an hexadecimal representation of a MAJ.MIN.MICRO version number.
  74. */
  75. static inline constexpr
  76. uint32_t d_version(const uint8_t major, const uint8_t minor, const uint8_t micro) noexcept
  77. {
  78. return uint32_t(major << 16) | uint32_t(minor << 8) | (micro << 0);
  79. }
  80. /**
  81. Dummy, no-op function.
  82. */
  83. static inline
  84. void d_pass() noexcept {}
  85. /** @} */
  86. /* --------------------------------------------------------------------------------------------------------------------
  87. * string print functions */
  88. /**
  89. @defgroup StringPrintFunctions String print functions
  90. @{
  91. */
  92. /*
  93. * Internal noexcept-safe fopen function.
  94. */
  95. static inline
  96. FILE* __d_fopen(const char* const filename, FILE* const fallback) noexcept
  97. {
  98. if (std::getenv("DPF_CAPTURE_CONSOLE_OUTPUT") == nullptr)
  99. return fallback;
  100. FILE* ret = nullptr;
  101. try {
  102. ret = std::fopen(filename, "a+");
  103. } catch (...) {}
  104. if (ret == nullptr)
  105. ret = fallback;
  106. return ret;
  107. }
  108. /**
  109. Print a string to stdout with newline (gray color).
  110. Does nothing if DEBUG is not defined.
  111. */
  112. #ifndef DEBUG
  113. # define d_debug(...)
  114. #else
  115. static inline
  116. void d_debug(const char* const fmt, ...) noexcept
  117. {
  118. static FILE* const output = __d_fopen("/tmp/dpf.debug.log", stdout);
  119. try {
  120. va_list args;
  121. va_start(args, fmt);
  122. if (output == stdout)
  123. {
  124. #ifdef DISTRHO_OS_MAC
  125. std::fprintf(output, "\x1b[37;1m[dpf] ");
  126. #else
  127. std::fprintf(output, "\x1b[30;1m[dpf] ");
  128. #endif
  129. std::vfprintf(output, fmt, args);
  130. std::fprintf(output, "\x1b[0m\n");
  131. }
  132. else
  133. {
  134. std::fprintf(output, "[dpf] ");
  135. std::vfprintf(output, fmt, args);
  136. std::fprintf(output, "\n");
  137. }
  138. std::fflush(output);
  139. va_end(args);
  140. } catch (...) {}
  141. }
  142. #endif
  143. /**
  144. Print a string to stdout with newline.
  145. */
  146. static inline
  147. void d_stdout(const char* const fmt, ...) noexcept
  148. {
  149. static FILE* const output = __d_fopen("/tmp/dpf.stdout.log", stdout);
  150. try {
  151. va_list args;
  152. va_start(args, fmt);
  153. std::fprintf(output, "[dpf] ");
  154. std::vfprintf(output, fmt, args);
  155. std::fprintf(output, "\n");
  156. #ifndef DEBUG
  157. if (output != stdout)
  158. #endif
  159. std::fflush(output);
  160. va_end(args);
  161. } catch (...) {}
  162. }
  163. /**
  164. Print a string to stderr with newline.
  165. */
  166. static inline
  167. void d_stderr(const char* const fmt, ...) noexcept
  168. {
  169. static FILE* const output = __d_fopen("/tmp/dpf.stderr.log", stderr);
  170. try {
  171. va_list args;
  172. va_start(args, fmt);
  173. std::fprintf(output, "[dpf] ");
  174. std::vfprintf(output, fmt, args);
  175. std::fprintf(output, "\n");
  176. #ifndef DEBUG
  177. if (output != stderr)
  178. #endif
  179. std::fflush(output);
  180. va_end(args);
  181. } catch (...) {}
  182. }
  183. /**
  184. Print a string to stderr with newline (red color).
  185. */
  186. static inline
  187. void d_stderr2(const char* const fmt, ...) noexcept
  188. {
  189. static FILE* const output = __d_fopen("/tmp/dpf.stderr2.log", stderr);
  190. try {
  191. va_list args;
  192. va_start(args, fmt);
  193. if (output == stdout)
  194. {
  195. std::fprintf(output, "\x1b[31m[dpf] ");
  196. std::vfprintf(output, fmt, args);
  197. std::fprintf(output, "\x1b[0m\n");
  198. }
  199. else
  200. {
  201. std::fprintf(output, "[dpf] ");
  202. std::vfprintf(output, fmt, args);
  203. std::fprintf(output, "\n");
  204. }
  205. std::fflush(output);
  206. va_end(args);
  207. } catch (...) {}
  208. }
  209. /**
  210. Print a safe assertion error message.
  211. */
  212. static inline
  213. void d_safe_assert(const char* const assertion, const char* const file, const int line) noexcept
  214. {
  215. d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
  216. }
  217. /**
  218. Print a safe assertion error message, with 1 extra signed integer value.
  219. */
  220. static inline
  221. void d_safe_assert_int(const char* const assertion, const char* const file,
  222. const int line, const int value) noexcept
  223. {
  224. d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
  225. }
  226. /**
  227. Print a safe assertion error message, with 1 extra unsigned integer value.
  228. */
  229. static inline
  230. void d_safe_assert_uint(const char* const assertion, const char* const file,
  231. const int line, const uint value) noexcept
  232. {
  233. d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value);
  234. }
  235. /**
  236. Print a safe assertion error message, with 2 extra signed integer values.
  237. */
  238. static inline
  239. void d_safe_assert_int2(const char* const assertion, const char* const file,
  240. const int line, const int v1, const int v2) noexcept
  241. {
  242. d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
  243. }
  244. /**
  245. Print a safe assertion error message, with 2 extra unsigned integer values.
  246. */
  247. static inline
  248. void d_safe_assert_uint2(const char* const assertion, const char* const file,
  249. const int line, const uint v1, const uint v2) noexcept
  250. {
  251. d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2);
  252. }
  253. /**
  254. Print a safe assertion error message, with a custom error message.
  255. */
  256. static inline
  257. void d_custom_safe_assert(const char* const message, const char* const assertion, const char* const file,
  258. const int line) noexcept
  259. {
  260. d_stderr2("assertion failure: %s, condition \"%s\" in file %s, line %i", message, assertion, file, line);
  261. }
  262. /**
  263. Print a safe exception error message.
  264. */
  265. static inline
  266. void d_safe_exception(const char* const exception, const char* const file, const int line) noexcept
  267. {
  268. d_stderr2("exception caught: \"%s\" in file %s, line %i", exception, file, line);
  269. }
  270. /** @} */
  271. /* --------------------------------------------------------------------------------------------------------------------
  272. * math functions */
  273. /**
  274. @defgroup MathFunctions Math related functions
  275. @{
  276. */
  277. /**
  278. Safely compare two floating point numbers.
  279. Returns true if they match.
  280. */
  281. template<typename T>
  282. static inline constexpr
  283. bool d_isEqual(const T& v1, const T& v2)
  284. {
  285. return std::abs(v1-v2) < std::numeric_limits<T>::epsilon();
  286. }
  287. /**
  288. Safely compare two floating point numbers.
  289. Returns true if they don't match.
  290. */
  291. template<typename T>
  292. static inline constexpr
  293. bool d_isNotEqual(const T& v1, const T& v2)
  294. {
  295. return std::abs(v1-v2) >= std::numeric_limits<T>::epsilon();
  296. }
  297. /**
  298. Safely check if a floating point number is zero.
  299. */
  300. template<typename T>
  301. static inline constexpr
  302. bool d_isZero(const T& value)
  303. {
  304. return std::abs(value) < std::numeric_limits<T>::epsilon();
  305. }
  306. /**
  307. Safely check if a floating point number is not zero.
  308. */
  309. template<typename T>
  310. static inline constexpr
  311. bool d_isNotZero(const T& value)
  312. {
  313. return std::abs(value) >= std::numeric_limits<T>::epsilon();
  314. }
  315. /**
  316. Get next power of 2.
  317. */
  318. static inline
  319. uint32_t d_nextPowerOf2(uint32_t size) noexcept
  320. {
  321. DISTRHO_SAFE_ASSERT_RETURN(size > 0, 0);
  322. // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
  323. --size;
  324. size |= size >> 1;
  325. size |= size >> 2;
  326. size |= size >> 4;
  327. size |= size >> 8;
  328. size |= size >> 16;
  329. return ++size;
  330. }
  331. /**
  332. Round a floating point number to an integer.
  333. Fast operation for values known to be 0 or positive.
  334. */
  335. template<typename T>
  336. static inline constexpr
  337. int32_t d_roundToIntPositive(const T& value)
  338. {
  339. return static_cast<int32_t>(value + static_cast<T>(0.5));
  340. }
  341. /**
  342. Round a floating point number to an unsigned integer.
  343. Fast operation for values known to be 0 or positive.
  344. */
  345. template<typename T>
  346. static inline constexpr
  347. uint32_t d_roundToUnsignedInt(const T& value)
  348. {
  349. return static_cast<uint32_t>(value + static_cast<T>(0.5));
  350. }
  351. /**
  352. Round a floating point number to an integer.
  353. Fast operation for values known to be 0 or negative.
  354. */
  355. template<typename T>
  356. static inline constexpr
  357. int32_t d_roundToIntNegative(const T& value)
  358. {
  359. return static_cast<int32_t>(value - static_cast<T>(0.5));
  360. }
  361. /**
  362. Round a floating point number to integer.
  363. */
  364. template<typename T>
  365. static inline constexpr
  366. int32_t d_roundToInt(const T& value)
  367. {
  368. return value >= 0 ? static_cast<int32_t>(value + static_cast<T>(0.5))
  369. : static_cast<int32_t>(value - static_cast<T>(0.5));
  370. }
  371. /** @} */
  372. /* --------------------------------------------------------------------------------------------------------------------
  373. * other stuff */
  374. #ifndef DONT_SET_USING_DISTRHO_NAMESPACE
  375. /**
  376. If your code uses a lot of DISTRHO classes, then this will obviously save you a lot of typing,
  377. but can be disabled by setting DONT_SET_USING_DISTRHO_NAMESPACE.
  378. */
  379. namespace DISTRHO_NAMESPACE {}
  380. using namespace DISTRHO_NAMESPACE;
  381. #endif
  382. #endif // DISTRHO_UTILS_HPP_INCLUDED