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.

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