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.

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