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.

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