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.

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