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.

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