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.

391 lines
11KB

  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