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.

687 lines
15KB

  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_bridge_osc.hpp"
  24. #include "rt_list.hpp"
  25. #include <QtGui/QMainWindow>
  26. #define CARLA_DECLARE_NON_COPY_STRUCT(structName) \
  27. structName(const structName&) = delete;
  28. #define CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(structName) \
  29. CARLA_DECLARE_NON_COPY_STRUCT(structName) \
  30. CARLA_LEAK_DETECTOR(structName)
  31. #define CARLA_PROCESS_CONTINUE_CHECK if (! fData->enabled) { fData->engine->callback(CALLBACK_DEBUG, fData->id, 0, 0, 0.0, nullptr); return; }
  32. CARLA_BACKEND_START_NAMESPACE
  33. // -----------------------------------------------------------------------
  34. struct PluginAudioPort {
  35. uint32_t rindex;
  36. CarlaEngineAudioPort* port;
  37. PluginAudioPort()
  38. : rindex(0),
  39. port(nullptr) {}
  40. ~PluginAudioPort()
  41. {
  42. CARLA_ASSERT(port == nullptr);
  43. }
  44. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginAudioPort)
  45. };
  46. struct PluginAudioData {
  47. uint32_t count;
  48. PluginAudioPort* ports;
  49. PluginAudioData()
  50. : count(0),
  51. ports(nullptr) {}
  52. ~PluginAudioData()
  53. {
  54. CARLA_ASSERT(ports == nullptr);
  55. }
  56. void createNew(const size_t count)
  57. {
  58. CARLA_ASSERT(ports == nullptr);
  59. if (ports == nullptr)
  60. ports = new PluginAudioPort[count];
  61. this->count = count;
  62. }
  63. void freePorts()
  64. {
  65. for (uint32_t i=0; i < count; i++)
  66. {
  67. if (ports[i].port != nullptr)
  68. {
  69. delete ports[i].port;
  70. ports[i].port = nullptr;
  71. }
  72. }
  73. }
  74. void clear()
  75. {
  76. freePorts();
  77. if (ports != nullptr)
  78. {
  79. delete[] ports;
  80. ports = nullptr;
  81. }
  82. count = 0;
  83. }
  84. void initBuffers(CarlaEngine* const engine)
  85. {
  86. for (uint32_t i=0; i < count; i++)
  87. {
  88. if (ports[i].port != nullptr)
  89. ports[i].port->initBuffer(engine);
  90. }
  91. }
  92. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginAudioData)
  93. };
  94. // -----------------------------------------------------------------------
  95. struct PluginEventData {
  96. CarlaEngineEventPort* portIn;
  97. CarlaEngineEventPort* portOut;
  98. PluginEventData()
  99. : portIn(nullptr),
  100. portOut(nullptr) {}
  101. ~PluginEventData()
  102. {
  103. CARLA_ASSERT(portIn == nullptr);
  104. CARLA_ASSERT(portOut == nullptr);
  105. }
  106. void freePorts()
  107. {
  108. if (portIn != nullptr)
  109. {
  110. delete portIn;
  111. portIn = nullptr;
  112. }
  113. if (portOut != nullptr)
  114. {
  115. delete portOut;
  116. portOut = nullptr;
  117. }
  118. }
  119. void clear()
  120. {
  121. freePorts();
  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 size_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. }
  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. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginParameterData)
  170. };
  171. // -----------------------------------------------------------------------
  172. typedef const char* ProgramName;
  173. struct PluginProgramData {
  174. uint32_t count;
  175. int32_t current;
  176. ProgramName* names;
  177. PluginProgramData()
  178. : count(0),
  179. current(-1),
  180. names(nullptr) {}
  181. ~PluginProgramData()
  182. {
  183. CARLA_ASSERT(names == nullptr);
  184. }
  185. void createNew(const uint32_t count)
  186. {
  187. CARLA_ASSERT(names == nullptr);
  188. if (names == nullptr)
  189. names = new ProgramName[count];
  190. for (uint32_t i=0; i < count; i++)
  191. names[i] = nullptr;
  192. this->count = count;
  193. }
  194. void clear()
  195. {
  196. if (names != nullptr)
  197. {
  198. for (uint32_t i=0; i < count; i++)
  199. std::free((void*)names[i]);
  200. delete[] names;
  201. names = nullptr;
  202. }
  203. count = 0;
  204. current = -1;
  205. }
  206. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginProgramData)
  207. };
  208. // -----------------------------------------------------------------------
  209. struct PluginMidiProgramData {
  210. uint32_t count;
  211. int32_t current;
  212. MidiProgramData* data;
  213. PluginMidiProgramData()
  214. : count(0),
  215. current(-1),
  216. data(nullptr) {}
  217. ~PluginMidiProgramData()
  218. {
  219. CARLA_ASSERT(data == nullptr);
  220. }
  221. void createNew(const uint32_t count)
  222. {
  223. CARLA_ASSERT(data == nullptr);
  224. if (data == nullptr)
  225. data = new MidiProgramData[count];
  226. this->count = count;
  227. }
  228. void clear()
  229. {
  230. if (data != nullptr)
  231. {
  232. delete[] data;
  233. data = nullptr;
  234. }
  235. count = 0;
  236. current = -1;
  237. }
  238. const MidiProgramData& getCurrent() const
  239. {
  240. CARLA_ASSERT(current >= 0 && current < static_cast<int32_t>(count));
  241. return data[current];
  242. }
  243. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginMidiProgramData)
  244. };
  245. // -----------------------------------------------------------------------
  246. struct PluginPostRtEvent {
  247. PluginPostRtEventType type;
  248. int32_t value1;
  249. int32_t value2;
  250. double value3;
  251. PluginPostRtEvent()
  252. : type(kPluginPostRtEventNull),
  253. value1(-1),
  254. value2(-1),
  255. value3(0.0) {}
  256. CARLA_DECLARE_NON_COPY_STRUCT(PluginPostRtEvent)
  257. };
  258. // -----------------------------------------------------------------------
  259. struct ExternalMidiNote {
  260. int8_t channel; // invalid = -1
  261. uint8_t note;
  262. uint8_t velo;
  263. ExternalMidiNote()
  264. : channel(-1),
  265. note(0),
  266. velo(0) {}
  267. CARLA_DECLARE_NON_COPY_STRUCT(ExternalMidiNote)
  268. };
  269. // -----------------------------------------------------------------------
  270. class CarlaPluginGUI : public QMainWindow
  271. {
  272. public:
  273. CarlaPluginGUI(QWidget* const parent = nullptr);
  274. ~CarlaPluginGUI();
  275. private:
  276. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginGUI)
  277. };
  278. // -----------------------------------------------------------------------
  279. const unsigned short MIN_RT_EVENTS = 152;
  280. const unsigned short MAX_RT_EVENTS = 512;
  281. const unsigned int PLUGIN_OPTION2_HAS_MIDI_IN = 0x1;
  282. const unsigned int PLUGIN_OPTION2_HAS_MIDI_OUT = 0x2;
  283. // -----------------------------------------------------------------------
  284. struct CarlaPluginProtectedData {
  285. unsigned int id;
  286. CarlaEngine* const engine;
  287. CarlaEngineClient* client;
  288. CarlaPluginGUI* gui;
  289. unsigned int hints;
  290. unsigned int options;
  291. unsigned int options2;
  292. bool active;
  293. bool activeBefore;
  294. bool enabled;
  295. void* lib;
  296. CarlaString name;
  297. CarlaString filename;
  298. // misc
  299. int8_t ctrlInChannel;
  300. #if 0
  301. uint32_t latency;
  302. float** latencyBuffers;
  303. #endif
  304. // data
  305. PluginAudioData audioIn;
  306. PluginAudioData audioOut;
  307. PluginEventData event;
  308. PluginParameterData param;
  309. PluginProgramData prog;
  310. PluginMidiProgramData midiprog;
  311. NonRtListNew<CustomData> custom;
  312. struct ExternalNotes {
  313. CarlaMutex mutex;
  314. RtList<ExternalMidiNote> data;
  315. ExternalNotes()
  316. : data(32, 512) {}
  317. void append(const ExternalMidiNote& note)
  318. {
  319. data.append_sleepy(note);
  320. }
  321. } extNotes;
  322. struct PostRtEvents {
  323. CarlaMutex mutex;
  324. RtList<PluginPostRtEvent> data;
  325. RtList<PluginPostRtEvent> dataPendingRT;
  326. PostRtEvents()
  327. : data(MIN_RT_EVENTS, MAX_RT_EVENTS),
  328. dataPendingRT(MIN_RT_EVENTS, MAX_RT_EVENTS) {}
  329. void appendRT(const PluginPostRtEvent& event)
  330. {
  331. dataPendingRT.append(event);
  332. if (mutex.tryLock())
  333. {
  334. dataPendingRT.splice(data, true);
  335. mutex.unlock();
  336. }
  337. }
  338. //void appendNonRT(const PluginPostRtEvent& event)
  339. //{
  340. // data.append_sleepy(event);
  341. //}
  342. } postRtEvents;
  343. struct PostProc {
  344. float dryWet;
  345. float volume;
  346. float balanceLeft;
  347. float balanceRight;
  348. float panning;
  349. PostProc()
  350. : dryWet(1.0f),
  351. volume(1.0f),
  352. balanceLeft(-1.0f),
  353. balanceRight(1.0f),
  354. panning(0.0f) {}
  355. } postProc;
  356. struct OSC {
  357. CarlaOscData data;
  358. CarlaPluginThread* thread;
  359. OSC()
  360. : thread(nullptr) {}
  361. } osc;
  362. CarlaPluginProtectedData(CarlaEngine* const engine_, const unsigned short id_)
  363. : id(id_),
  364. engine(engine_),
  365. client(nullptr),
  366. gui(nullptr),
  367. hints(0x0),
  368. options(0x0),
  369. options2(0x0),
  370. active(false),
  371. activeBefore(false),
  372. enabled(false),
  373. lib(nullptr),
  374. ctrlInChannel(-1) {}
  375. #if 0
  376. latency(0),
  377. latencyBuffers(nullptr) {}
  378. #endif
  379. CarlaPluginProtectedData() = delete;
  380. CARLA_LEAK_DETECTOR(CarlaPluginProtectedData)
  381. };
  382. // -----------------------------------------------------------------------
  383. CARLA_BACKEND_END_NAMESPACE
  384. #endif // __CARLA_PLUGIN_INTERNAL_HPP__
  385. // common includes
  386. //#include <cmath>
  387. //#include <vector>
  388. //#include <QtCore/QMutex>
  389. //#include <QtGui/QMainWindow>
  390. //#ifdef Q_WS_X11
  391. //# include <QtGui/QX11EmbedContainer>
  392. //typedef QX11EmbedContainer GuiContainer;
  393. //#else
  394. //# include <QtGui/QWidget>
  395. //typedef QWidget GuiContainer;
  396. //#endif
  397. #if 0
  398. // -------------------------------------------------------------------
  399. // Extra
  400. ExternalMidiNote extMidiNotes[MAX_MIDI_EVENTS];
  401. // -------------------------------------------------------------------
  402. // Utilities
  403. static double fixParameterValue(double& value, const ParameterRanges& ranges)
  404. {
  405. if (value < ranges.min)
  406. value = ranges.min;
  407. else if (value > ranges.max)
  408. value = ranges.max;
  409. return value;
  410. }
  411. static float fixParameterValue(float& value, const ParameterRanges& ranges)
  412. {
  413. if (value < ranges.min)
  414. value = ranges.min;
  415. else if (value > ranges.max)
  416. value = ranges.max;
  417. return value;
  418. }
  419. friend class CarlaEngine; // FIXME
  420. friend class CarlaEngineJack;
  421. #endif
  422. #if 0
  423. // -------------------------------------------------------------------
  424. /*!
  425. * \class ScopedDisabler
  426. *
  427. * \brief Carla plugin scoped disabler
  428. *
  429. * This is a handy class that temporarily disables a plugin during a function scope.\n
  430. * It should be used when the plugin needs reload or state change, something like this:
  431. * \code
  432. * {
  433. * const CarlaPlugin::ScopedDisabler m(plugin);
  434. * plugin->setChunkData(data);
  435. * }
  436. * \endcode
  437. */
  438. class ScopedDisabler
  439. {
  440. public:
  441. /*!
  442. * Disable plugin \a plugin if \a disable is true.
  443. * The plugin is re-enabled in the deconstructor of this class if \a disable is true.
  444. *
  445. * \param plugin The plugin to disable
  446. * \param disable Wherever to disable the plugin or not, true by default
  447. */
  448. ScopedDisabler(CarlaPlugin* const plugin, const bool disable = true)
  449. : m_plugin(plugin),
  450. m_disable(disable)
  451. {
  452. if (m_disable)
  453. {
  454. m_plugin->engineProcessLock();
  455. m_plugin->setEnabled(false);
  456. m_plugin->engineProcessUnlock();
  457. }
  458. }
  459. ~ScopedDisabler()
  460. {
  461. if (m_disable)
  462. {
  463. m_plugin->engineProcessLock();
  464. m_plugin->setEnabled(true);
  465. m_plugin->engineProcessUnlock();
  466. }
  467. }
  468. private:
  469. CarlaPlugin* const m_plugin;
  470. const bool m_disable;
  471. };
  472. /*!
  473. * \class CarlaPluginGUI
  474. *
  475. * \brief Carla Backend gui plugin class
  476. *
  477. * \see CarlaPlugin
  478. */
  479. class CarlaPluginGUI : public QMainWindow
  480. {
  481. public:
  482. /*!
  483. * \class Callback
  484. *
  485. * \brief Carla plugin GUI callback
  486. */
  487. class Callback
  488. {
  489. public:
  490. virtual ~Callback() {}
  491. virtual void guiClosedCallback() = 0;
  492. };
  493. // -------------------------------------------------------------------
  494. // Constructor and destructor
  495. /*!
  496. * TODO
  497. */
  498. CarlaPluginGUI(QWidget* const parent, Callback* const callback);
  499. /*!
  500. * TODO
  501. */
  502. ~CarlaPluginGUI();
  503. // -------------------------------------------------------------------
  504. // Get data
  505. /*!
  506. * TODO
  507. */
  508. GuiContainer* getContainer() const;
  509. /*!
  510. * TODO
  511. */
  512. WId getWinId() const;
  513. // -------------------------------------------------------------------
  514. // Set data
  515. /*!
  516. * TODO
  517. */
  518. void setNewSize(const int width, const int height);
  519. /*!
  520. * TODO
  521. */
  522. void setResizable(const bool resizable);
  523. /*!
  524. * TODO
  525. */
  526. void setTitle(const char* const title);
  527. /*!
  528. * TODO
  529. */
  530. void setVisible(const bool yesNo);
  531. // -------------------------------------------------------------------
  532. private:
  533. Callback* const m_callback;
  534. GuiContainer* m_container;
  535. QByteArray m_geometry;
  536. bool m_resizable;
  537. void hideEvent(QHideEvent* const event);
  538. void closeEvent(QCloseEvent* const event);
  539. };
  540. #endif