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.

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