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.

691 lines
16KB

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