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.

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