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.

622 lines
15KB

  1. /*
  2. * Carla Plugin
  3. * Copyright (C) 2011-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 GPL.txt file
  16. */
  17. #ifndef __CARLA_PLUGIN_INTERNAL_HPP__
  18. #define __CARLA_PLUGIN_INTERNAL_HPP__
  19. #include "CarlaBackendUtils.hpp"
  20. #include "CarlaPluginThread.hpp"
  21. #include "CarlaPlugin.hpp"
  22. #include "CarlaEngine.hpp"
  23. #include "CarlaOscUtils.hpp"
  24. #include "CarlaStateUtils.hpp"
  25. #include "CarlaMutex.hpp"
  26. #include "CarlaMIDI.h"
  27. #include "RtList.hpp"
  28. #include <QtGui/QMainWindow>
  29. #ifdef Q_WS_X11
  30. # include <QtGui/QX11EmbedContainer>
  31. typedef QX11EmbedContainer GuiContainer;
  32. #else
  33. # include <QtGui/QWidget>
  34. typedef QWidget GuiContainer;
  35. #endif
  36. #define CARLA_DECLARE_NON_COPY_STRUCT(structName) \
  37. structName(structName&) = delete; \
  38. structName(const structName&) = delete;
  39. #define CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(structName) \
  40. CARLA_DECLARE_NON_COPY_STRUCT(structName) \
  41. CARLA_LEAK_DETECTOR(structName)
  42. #define CARLA_PROCESS_CONTINUE_CHECK if (! fEnabled) { kData->engine->callback(CALLBACK_DEBUG, fId, 0, 0, 0.0, nullptr); return; }
  43. CARLA_BACKEND_START_NAMESPACE
  44. // -----------------------------------------------------------------------
  45. const unsigned short MAX_RT_EVENTS = 128;
  46. const unsigned short MAX_MIDI_EVENTS = 512;
  47. const unsigned int PLUGIN_HINT_HAS_MIDI_IN = 0x1;
  48. const unsigned int PLUGIN_HINT_HAS_MIDI_OUT = 0x2;
  49. const unsigned int PLUGIN_HINT_CAN_RUN_RACK = 0x4;
  50. // -----------------------------------------------------------------------
  51. struct PluginAudioPort {
  52. uint32_t rindex;
  53. CarlaEngineAudioPort* port;
  54. PluginAudioPort()
  55. : rindex(0),
  56. port(nullptr) {}
  57. ~PluginAudioPort()
  58. {
  59. CARLA_ASSERT(port == nullptr);
  60. }
  61. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginAudioPort)
  62. };
  63. struct PluginAudioData {
  64. uint32_t count;
  65. PluginAudioPort* ports;
  66. PluginAudioData()
  67. : count(0),
  68. ports(nullptr) {}
  69. ~PluginAudioData()
  70. {
  71. CARLA_ASSERT_INT(count == 0, count);
  72. CARLA_ASSERT(ports == nullptr);
  73. }
  74. void createNew(const uint32_t newCount)
  75. {
  76. CARLA_ASSERT_INT(count == 0, count);
  77. CARLA_ASSERT(ports == nullptr);
  78. CARLA_ASSERT_INT(newCount > 0, newCount);
  79. if (ports != nullptr || newCount == 0)
  80. return;
  81. ports = new PluginAudioPort[newCount];
  82. count = newCount;
  83. }
  84. void clear()
  85. {
  86. if (ports != nullptr)
  87. {
  88. for (uint32_t i=0; i < count; i++)
  89. {
  90. if (ports[i].port != nullptr)
  91. {
  92. delete ports[i].port;
  93. ports[i].port = nullptr;
  94. }
  95. }
  96. delete[] ports;
  97. ports = nullptr;
  98. }
  99. count = 0;
  100. }
  101. void initBuffers(CarlaEngine* const engine)
  102. {
  103. for (uint32_t i=0; i < count; i++)
  104. {
  105. if (ports[i].port != nullptr)
  106. ports[i].port->initBuffer(engine);
  107. }
  108. }
  109. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginAudioData)
  110. };
  111. // -----------------------------------------------------------------------
  112. struct PluginEventData {
  113. CarlaEngineEventPort* portIn;
  114. CarlaEngineEventPort* portOut;
  115. PluginEventData()
  116. : portIn(nullptr),
  117. portOut(nullptr) {}
  118. ~PluginEventData()
  119. {
  120. CARLA_ASSERT(portIn == nullptr);
  121. CARLA_ASSERT(portOut == nullptr);
  122. }
  123. void clear()
  124. {
  125. if (portIn != nullptr)
  126. {
  127. delete portIn;
  128. portIn = nullptr;
  129. }
  130. if (portOut != nullptr)
  131. {
  132. delete portOut;
  133. portOut = nullptr;
  134. }
  135. }
  136. void initBuffers(CarlaEngine* const engine)
  137. {
  138. if (portIn != nullptr)
  139. portIn->initBuffer(engine);
  140. if (portOut != nullptr)
  141. portOut->initBuffer(engine);
  142. }
  143. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginEventData)
  144. };
  145. // -----------------------------------------------------------------------
  146. struct PluginParameterData {
  147. uint32_t count;
  148. ParameterData* data;
  149. ParameterRanges* ranges;
  150. PluginParameterData()
  151. : count(0),
  152. data(nullptr),
  153. ranges(nullptr) {}
  154. ~PluginParameterData()
  155. {
  156. CARLA_ASSERT_INT(count == 0, count);
  157. CARLA_ASSERT(data == nullptr);
  158. CARLA_ASSERT(ranges == nullptr);
  159. }
  160. void createNew(const uint32_t newCount)
  161. {
  162. CARLA_ASSERT_INT(count == 0, count);
  163. CARLA_ASSERT(data == nullptr);
  164. CARLA_ASSERT(ranges == nullptr);
  165. CARLA_ASSERT_INT(newCount > 0, newCount);
  166. if (data != nullptr || ranges != nullptr || newCount == 0)
  167. return;
  168. data = new ParameterData[newCount];
  169. ranges = new ParameterRanges[newCount];
  170. count = newCount;
  171. }
  172. void clear()
  173. {
  174. if (data != nullptr)
  175. {
  176. delete[] data;
  177. data = nullptr;
  178. }
  179. if (ranges != nullptr)
  180. {
  181. delete[] ranges;
  182. ranges = nullptr;
  183. }
  184. count = 0;
  185. }
  186. float fixValue(const uint32_t parameterId, const float& value)
  187. {
  188. CARLA_ASSERT(parameterId < count);
  189. return ranges[parameterId].fixValue(value);
  190. }
  191. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginParameterData)
  192. };
  193. // -----------------------------------------------------------------------
  194. typedef const char* ProgramName;
  195. struct PluginProgramData {
  196. uint32_t count;
  197. int32_t current;
  198. ProgramName* names;
  199. PluginProgramData()
  200. : count(0),
  201. current(-1),
  202. names(nullptr) {}
  203. ~PluginProgramData()
  204. {
  205. CARLA_ASSERT_INT(count == 0, count);
  206. CARLA_ASSERT_INT(current == -1, current);
  207. CARLA_ASSERT(names == nullptr);
  208. }
  209. void createNew(const uint32_t newCount)
  210. {
  211. CARLA_ASSERT_INT(count == 0, count);
  212. CARLA_ASSERT_INT(current == -1, current);
  213. CARLA_ASSERT(names == nullptr);
  214. CARLA_ASSERT_INT(newCount > 0, newCount);
  215. if (names != nullptr || newCount == 0)
  216. return;
  217. names = new ProgramName[newCount];
  218. count = newCount;
  219. for (uint32_t i=0; i < newCount; i++)
  220. names[i] = nullptr;
  221. }
  222. void clear()
  223. {
  224. if (names != nullptr)
  225. {
  226. for (uint32_t i=0; i < count; i++)
  227. {
  228. if (names[i] != nullptr)
  229. delete[] names[i];
  230. }
  231. delete[] names;
  232. names = nullptr;
  233. }
  234. count = 0;
  235. current = -1;
  236. }
  237. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginProgramData)
  238. };
  239. // -----------------------------------------------------------------------
  240. struct PluginMidiProgramData {
  241. uint32_t count;
  242. int32_t current;
  243. MidiProgramData* data;
  244. PluginMidiProgramData()
  245. : count(0),
  246. current(-1),
  247. data(nullptr) {}
  248. ~PluginMidiProgramData()
  249. {
  250. CARLA_ASSERT_INT(count == 0, count);
  251. CARLA_ASSERT_INT(current == -1, current);
  252. CARLA_ASSERT(data == nullptr);
  253. }
  254. void createNew(const uint32_t newCount)
  255. {
  256. CARLA_ASSERT_INT(count == 0, count);
  257. CARLA_ASSERT_INT(current == -1, current);
  258. CARLA_ASSERT(data == nullptr);
  259. CARLA_ASSERT_INT(newCount > 0, newCount);
  260. if (data != nullptr || newCount == 0)
  261. return;
  262. data = new MidiProgramData[newCount];
  263. count = newCount;
  264. }
  265. void clear()
  266. {
  267. if (data != nullptr)
  268. {
  269. delete[] data;
  270. data = nullptr;
  271. }
  272. count = 0;
  273. current = -1;
  274. }
  275. const MidiProgramData& getCurrent() const
  276. {
  277. CARLA_ASSERT(current >= 0 && current < static_cast<int32_t>(count));
  278. return data[current];
  279. }
  280. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginMidiProgramData)
  281. };
  282. // -----------------------------------------------------------------------
  283. struct PluginPostRtEvent {
  284. PluginPostRtEventType type;
  285. int32_t value1;
  286. int32_t value2;
  287. float value3;
  288. PluginPostRtEvent()
  289. : type(kPluginPostRtEventNull),
  290. value1(-1),
  291. value2(-1),
  292. value3(0.0f) {}
  293. #if 1//def DEBUG
  294. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginPostRtEvent)
  295. #else
  296. CARLA_DECLARE_NON_COPY_STRUCT(PluginPostRtEvent)
  297. #endif
  298. };
  299. // -----------------------------------------------------------------------
  300. struct ExternalMidiNote {
  301. int8_t channel; // invalid = -1
  302. uint8_t note;
  303. uint8_t velo;
  304. ExternalMidiNote()
  305. : channel(-1),
  306. note(0),
  307. velo(0) {}
  308. #if 1//def DEBUG
  309. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(ExternalMidiNote)
  310. #else
  311. CARLA_DECLARE_NON_COPY_STRUCT(ExternalMidiNote)
  312. #endif
  313. };
  314. // -----------------------------------------------------------------------
  315. class CarlaPluginGUI : public QMainWindow
  316. {
  317. public:
  318. class Callback
  319. {
  320. public:
  321. virtual ~Callback() {}
  322. virtual void guiClosedCallback() = 0;
  323. };
  324. CarlaPluginGUI(QWidget* const parent, Callback* const callback);
  325. ~CarlaPluginGUI();
  326. WId getWinId() const;
  327. protected:
  328. void closeEvent(QCloseEvent* const event);
  329. private:
  330. Callback* const kCallback;
  331. GuiContainer fContainer;
  332. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginGUI)
  333. };
  334. // -----------------------------------------------------------------------
  335. struct CarlaPluginProtectedData {
  336. CarlaEngine* const engine;
  337. CarlaEngineClient* client;
  338. CarlaPluginGUI* gui;
  339. bool active;
  340. bool activeBefore;
  341. bool needsReset;
  342. void* lib;
  343. // misc
  344. int8_t ctrlChannel;
  345. unsigned int extraHints;
  346. // latency
  347. uint32_t latency;
  348. float** latencyBuffers;
  349. // data
  350. PluginAudioData audioIn;
  351. PluginAudioData audioOut;
  352. PluginEventData event;
  353. PluginParameterData param;
  354. PluginProgramData prog;
  355. PluginMidiProgramData midiprog;
  356. NonRtList<CustomData> custom;
  357. CarlaMutex masterMutex; // global master lock
  358. CarlaMutex singleMutex; // small lock used only in processSingle()
  359. struct ExternalNotes {
  360. CarlaMutex mutex;
  361. RtList<ExternalMidiNote>::Pool dataPool;
  362. RtList<ExternalMidiNote> data;
  363. ExternalNotes()
  364. : dataPool(32, 152),
  365. data(&dataPool) {}
  366. ~ExternalNotes()
  367. {
  368. mutex.lock();
  369. data.clear();
  370. mutex.unlock();
  371. }
  372. void append(const ExternalMidiNote& note)
  373. {
  374. mutex.lock();
  375. data.append_sleepy(note);
  376. mutex.unlock();
  377. }
  378. ExternalNotes(ExternalNotes&) = delete;
  379. ExternalNotes(const ExternalNotes&) = delete;
  380. } extNotes;
  381. struct PostRtEvents {
  382. CarlaMutex mutex;
  383. RtList<PluginPostRtEvent>::Pool dataPool;
  384. RtList<PluginPostRtEvent> data;
  385. RtList<PluginPostRtEvent> dataPendingRT;
  386. PostRtEvents()
  387. : dataPool(MAX_RT_EVENTS, MAX_RT_EVENTS),
  388. data(&dataPool),
  389. dataPendingRT(&dataPool) {}
  390. ~PostRtEvents()
  391. {
  392. clear();
  393. }
  394. void appendRT(const PluginPostRtEvent& event)
  395. {
  396. dataPendingRT.append(event);
  397. }
  398. void trySplice()
  399. {
  400. if (mutex.tryLock())
  401. {
  402. dataPendingRT.spliceAppend(data, true);
  403. mutex.unlock();
  404. }
  405. }
  406. void clear()
  407. {
  408. mutex.lock();
  409. data.clear();
  410. dataPendingRT.clear();
  411. mutex.unlock();
  412. }
  413. PostRtEvents(PostRtEvents&) = delete;
  414. PostRtEvents(const PostRtEvents&) = delete;
  415. } postRtEvents;
  416. struct PostProc {
  417. float dryWet;
  418. float volume;
  419. float balanceLeft;
  420. float balanceRight;
  421. float panning;
  422. PostProc()
  423. : dryWet(1.0f),
  424. volume(1.0f),
  425. balanceLeft(-1.0f),
  426. balanceRight(1.0f),
  427. panning(0.0f) {}
  428. PostProc(PostProc&) = delete;
  429. PostProc(const PostProc&) = delete;
  430. } postProc;
  431. struct OSC {
  432. CarlaOscData data;
  433. CarlaPluginThread thread;
  434. OSC(CarlaEngine* const engine, CarlaPlugin* const plugin)
  435. : thread(engine, plugin) {}
  436. OSC() = delete;
  437. OSC(OSC&) = delete;
  438. OSC(const OSC&) = delete;
  439. } osc;
  440. CarlaPluginProtectedData(CarlaEngine* const engine_, CarlaPlugin* const plugin)
  441. : engine(engine_),
  442. client(nullptr),
  443. gui(nullptr),
  444. active(false),
  445. activeBefore(false),
  446. needsReset(false),
  447. lib(nullptr),
  448. ctrlChannel(0),
  449. extraHints(0x0),
  450. latency(0),
  451. latencyBuffers(nullptr),
  452. osc(engine, plugin) {}
  453. CarlaPluginProtectedData() = delete;
  454. CarlaPluginProtectedData(CarlaPluginProtectedData&) = delete;
  455. CarlaPluginProtectedData(const CarlaPluginProtectedData&) = delete;
  456. void createUiIfNeeded(CarlaPluginGUI::Callback* const callback)
  457. {
  458. if (gui != nullptr)
  459. return;
  460. gui = new CarlaPluginGUI(nullptr, callback);
  461. }
  462. void destroyUiIfNeeded()
  463. {
  464. if (gui == nullptr)
  465. return;
  466. gui->close();
  467. delete gui;
  468. gui = nullptr;
  469. }
  470. static CarlaEngine* getEngine(CarlaPlugin* const plugin)
  471. {
  472. return plugin->kData->engine;
  473. }
  474. static CarlaEngineAudioPort* getAudioInPort(CarlaPlugin* const plugin, const uint32_t index)
  475. {
  476. return plugin->kData->audioIn.ports[index].port;
  477. }
  478. static CarlaEngineAudioPort* getAudioOutPort(CarlaPlugin* const plugin, const uint32_t index)
  479. {
  480. return plugin->kData->audioOut.ports[index].port;
  481. }
  482. static bool canRunInRack(CarlaPlugin* const plugin)
  483. {
  484. return (plugin->kData->extraHints & PLUGIN_HINT_CAN_RUN_RACK);
  485. }
  486. CARLA_LEAK_DETECTOR(CarlaPluginProtectedData)
  487. };
  488. // -----------------------------------------------------------------------
  489. CARLA_BACKEND_END_NAMESPACE
  490. #endif // __CARLA_PLUGIN_INTERNAL_HPP__