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.

CarlaEngineInternal.hpp 11KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. * Carla Engine
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_ENGINE_INTERNAL_HPP_INCLUDED
  18. #define CARLA_ENGINE_INTERNAL_HPP_INCLUDED
  19. #include "CarlaEngine.hpp"
  20. #include "CarlaEngineOsc.hpp"
  21. #include "CarlaEngineThread.hpp"
  22. #include "CarlaPlugin.hpp"
  23. #include "CarlaMutex.hpp"
  24. #ifdef HAVE_JUCE
  25. # include "juce_audio_basics.h"
  26. using juce::FloatVectorOperations;
  27. #endif
  28. // -----------------------------------------------------------------------
  29. // Engine helper macro, sets lastError and returns false/NULL
  30. #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (cond) pass(); else { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return false; }
  31. #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (cond) pass(); else { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return nullptr; }
  32. // -----------------------------------------------------------------------
  33. // Float operations
  34. #ifdef HAVE_JUCE
  35. # define FLOAT_ADD(bufDst, bufSrc, frames) FloatVectorOperations::add(bufDst, bufSrc, frames)
  36. # define FLOAT_COPY(bufDst, bufSrc, frames) FloatVectorOperations::copy(bufDst, bufSrc, frames)
  37. # define FLOAT_CLEAR(buf, frames) FloatVectorOperations::clear(buf, frames)
  38. #else
  39. # define FLOAT_ADD(bufDst, bufSrc, frames) carla_addFloat(bufDst, bufSrc, frames)
  40. # define FLOAT_COPY(bufDst, bufSrc, frames) carla_copyFloat(bufDst, bufSrc, frames)
  41. # define FLOAT_CLEAR(buf, frames) carla_zeroFloat(buf, frames)
  42. #endif
  43. // -----------------------------------------------------------------------
  44. CARLA_BACKEND_START_NAMESPACE
  45. #if 0
  46. } // Fix editor indentation
  47. #endif
  48. // -----------------------------------------------------------------------
  49. static inline
  50. const char* EngineType2Str(const EngineType type)
  51. {
  52. switch (type)
  53. {
  54. case kEngineTypeNull:
  55. return "kEngineTypeNull";
  56. case kEngineTypeJack:
  57. return "kEngineTypeJack";
  58. case kEngineTypeJuce:
  59. return "kEngineTypeJuce";
  60. case kEngineTypeRtAudio:
  61. return "kEngineTypeRtAudio";
  62. case kEngineTypePlugin:
  63. return "kEngineTypePlugin";
  64. case kEngineTypeBridge:
  65. return "kEngineTypeBridge";
  66. }
  67. carla_stderr("CarlaBackend::EngineType2Str(%i) - invalid type", type);
  68. return nullptr;
  69. }
  70. static inline
  71. const char* EnginePortType2Str(const EnginePortType type)
  72. {
  73. switch (type)
  74. {
  75. case kEnginePortTypeNull:
  76. return "kEnginePortTypeNull";
  77. case kEnginePortTypeAudio:
  78. return "kEnginePortTypeAudio";
  79. case kEnginePortTypeCV:
  80. return "kEnginePortTypeCV";
  81. case kEnginePortTypeEvent:
  82. return "kEnginePortTypeEvent";
  83. }
  84. carla_stderr("CarlaBackend::EnginePortType2Str(%i) - invalid type", type);
  85. return nullptr;
  86. }
  87. static inline
  88. const char* EngineEventType2Str(const EngineEventType type)
  89. {
  90. switch (type)
  91. {
  92. case kEngineEventTypeNull:
  93. return "kEngineEventTypeNull";
  94. case kEngineEventTypeControl:
  95. return "kEngineEventTypeControl";
  96. case kEngineEventTypeMidi:
  97. return "kEngineEventTypeMidi";
  98. }
  99. carla_stderr("CarlaBackend::EngineEventType2Str(%i) - invalid type", type);
  100. return nullptr;
  101. }
  102. static inline
  103. const char* EngineControlEventType2Str(const EngineControlEventType type)
  104. {
  105. switch (type)
  106. {
  107. case kEngineControlEventTypeNull:
  108. return "kEngineNullEvent";
  109. case kEngineControlEventTypeParameter:
  110. return "kEngineControlEventTypeParameter";
  111. case kEngineControlEventTypeMidiBank:
  112. return "kEngineControlEventTypeMidiBank";
  113. case kEngineControlEventTypeMidiProgram:
  114. return "kEngineControlEventTypeMidiProgram";
  115. case kEngineControlEventTypeAllSoundOff:
  116. return "kEngineControlEventTypeAllSoundOff";
  117. case kEngineControlEventTypeAllNotesOff:
  118. return "kEngineControlEventTypeAllNotesOff";
  119. }
  120. carla_stderr("CarlaBackend::EngineControlEventType2Str(%i) - invalid type", type);
  121. return nullptr;
  122. }
  123. // -----------------------------------------------------------------------
  124. const unsigned short kEngineMaxInternalEventCount = 512;
  125. enum EnginePostAction {
  126. kEnginePostActionNull,
  127. kEnginePostActionZeroCount,
  128. kEnginePostActionRemovePlugin,
  129. kEnginePostActionSwitchPlugins
  130. };
  131. struct EnginePluginData {
  132. CarlaPlugin* plugin;
  133. float insPeak[2];
  134. float outsPeak[2];
  135. void clear()
  136. {
  137. plugin = nullptr;
  138. insPeak[0] = insPeak[1] = 0.0f;
  139. outsPeak[0] = outsPeak[1] = 0.0f;
  140. }
  141. };
  142. // -----------------------------------------------------------------------
  143. struct CarlaEngineProtectedData {
  144. CarlaEngineOsc osc;
  145. CarlaEngineThread thread;
  146. const CarlaOscData* oscData;
  147. EngineCallbackFunc callback;
  148. void* callbackPtr;
  149. unsigned int hints;
  150. uint32_t bufferSize;
  151. double sampleRate;
  152. bool aboutToClose; // don't re-activate thread if true
  153. unsigned int curPluginCount; // number of plugins loaded (0...max)
  154. unsigned int maxPluginNumber; // number of plugins allowed (0, 16, 99 or 255)
  155. unsigned int nextPluginId; // invalid if == maxPluginNumber
  156. CarlaString lastError;
  157. CarlaString name;
  158. EngineOptions options;
  159. EngineTimeInfo timeInfo;
  160. EnginePluginData* plugins;
  161. struct InternalEvents {
  162. EngineEvent* in;
  163. EngineEvent* out;
  164. InternalEvents() noexcept
  165. : in(nullptr),
  166. out(nullptr) {}
  167. ~InternalEvents()
  168. {
  169. CARLA_ASSERT(in == nullptr);
  170. CARLA_ASSERT(out == nullptr);
  171. }
  172. } bufEvents;
  173. struct InternalTime {
  174. bool playing;
  175. uint64_t frame;
  176. InternalTime() noexcept
  177. : playing(false),
  178. frame(0) {}
  179. } time;
  180. struct NextAction {
  181. EnginePostAction opcode;
  182. unsigned int pluginId;
  183. unsigned int value;
  184. CarlaMutex mutex;
  185. NextAction() noexcept
  186. : opcode(kEnginePostActionNull),
  187. pluginId(0),
  188. value(0) {}
  189. ~NextAction()
  190. {
  191. CARLA_ASSERT(opcode == kEnginePostActionNull);
  192. }
  193. void ready() noexcept
  194. {
  195. mutex.lock();
  196. mutex.unlock();
  197. }
  198. } nextAction;
  199. CarlaEngineProtectedData(CarlaEngine* const engine)
  200. : osc(engine),
  201. thread(engine),
  202. oscData(nullptr),
  203. callback(nullptr),
  204. callbackPtr(nullptr),
  205. hints(0x0),
  206. bufferSize(0),
  207. sampleRate(0.0),
  208. aboutToClose(false),
  209. curPluginCount(0),
  210. maxPluginNumber(0),
  211. nextPluginId(0),
  212. plugins(nullptr) {}
  213. #ifdef CARLA_PROPER_CPP11_SUPPORT
  214. CarlaEngineProtectedData() = delete;
  215. CARLA_DECLARE_NON_COPY_STRUCT(CarlaEngineProtectedData)
  216. #endif
  217. ~CarlaEngineProtectedData()
  218. {
  219. CARLA_ASSERT(curPluginCount == 0);
  220. CARLA_ASSERT(maxPluginNumber == 0);
  221. CARLA_ASSERT(nextPluginId == 0);
  222. CARLA_ASSERT(plugins == nullptr);
  223. }
  224. void doPluginRemove()
  225. {
  226. CARLA_ASSERT(curPluginCount > 0);
  227. CARLA_ASSERT(nextAction.pluginId < curPluginCount);
  228. --curPluginCount;
  229. // move all plugins 1 spot backwards
  230. for (unsigned int i=nextAction.pluginId; i < curPluginCount; ++i)
  231. {
  232. CarlaPlugin* const plugin(plugins[i+1].plugin);
  233. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  234. plugin->setId(i);
  235. plugins[i].plugin = plugin;
  236. plugins[i].insPeak[0] = 0.0f;
  237. plugins[i].insPeak[1] = 0.0f;
  238. plugins[i].outsPeak[0] = 0.0f;
  239. plugins[i].outsPeak[1] = 0.0f;
  240. }
  241. const unsigned int id(curPluginCount);
  242. // reset last plugin (now removed)
  243. plugins[id].plugin = nullptr;
  244. plugins[id].insPeak[0] = 0.0f;
  245. plugins[id].insPeak[1] = 0.0f;
  246. plugins[id].outsPeak[0] = 0.0f;
  247. plugins[id].outsPeak[1] = 0.0f;
  248. }
  249. void doPluginsSwitch()
  250. {
  251. CARLA_ASSERT(curPluginCount >= 2);
  252. const unsigned int idA(nextAction.pluginId);
  253. const unsigned int idB(nextAction.value);
  254. CARLA_ASSERT(idA < curPluginCount);
  255. CARLA_ASSERT(idB < curPluginCount);
  256. CARLA_ASSERT(plugins[idA].plugin != nullptr);
  257. CARLA_ASSERT(plugins[idB].plugin != nullptr);
  258. #if 0
  259. std::swap(plugins[idA].plugin, plugins[idB].plugin);
  260. #else
  261. CarlaPlugin* const tmp(plugins[idA].plugin);
  262. plugins[idA].plugin = plugins[idB].plugin;
  263. plugins[idB].plugin = tmp;
  264. #endif
  265. }
  266. void doNextPluginAction(const bool unlock) noexcept
  267. {
  268. switch (nextAction.opcode)
  269. {
  270. case kEnginePostActionNull:
  271. break;
  272. case kEnginePostActionZeroCount:
  273. curPluginCount = 0;
  274. break;
  275. case kEnginePostActionRemovePlugin:
  276. doPluginRemove();
  277. break;
  278. case kEnginePostActionSwitchPlugins:
  279. doPluginsSwitch();
  280. break;
  281. }
  282. nextAction.opcode = kEnginePostActionNull;
  283. nextAction.pluginId = 0;
  284. nextAction.value = 0;
  285. if (unlock)
  286. nextAction.mutex.unlock();
  287. }
  288. class ScopedActionLock
  289. {
  290. public:
  291. ScopedActionLock(CarlaEngineProtectedData* const data, const EnginePostAction action, const unsigned int pluginId, const unsigned int value, const bool lockWait)
  292. : fData(data)
  293. {
  294. fData->nextAction.mutex.lock();
  295. CARLA_ASSERT(fData->nextAction.opcode == kEnginePostActionNull);
  296. fData->nextAction.opcode = action;
  297. fData->nextAction.pluginId = pluginId;
  298. fData->nextAction.value = value;
  299. if (lockWait)
  300. {
  301. // block wait for unlock on processing side
  302. carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId);
  303. fData->nextAction.mutex.lock();
  304. carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId);
  305. }
  306. else
  307. {
  308. fData->doNextPluginAction(false);
  309. }
  310. }
  311. ~ScopedActionLock() noexcept
  312. {
  313. fData->nextAction.mutex.unlock();
  314. }
  315. private:
  316. CarlaEngineProtectedData* const fData;
  317. };
  318. };
  319. // -----------------------------------------------------------------------
  320. CARLA_BACKEND_END_NAMESPACE
  321. #endif // CARLA_ENGINE_INTERNAL_HPP_INCLUDED