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.

631 lines
14KB

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