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.

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