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.

578 lines
12KB

  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. #ifdef BUILD_BRIDGE
  23. # include "carla_bridge_osc.hpp"
  24. #else
  25. # include "carla_osc_utils.hpp"
  26. #endif
  27. #include "rt_list.hpp"
  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 (! fData->enabled) { fData->engine->callback(CALLBACK_DEBUG, fData->id, 0, 0, 0.0, nullptr); return; }
  34. CARLA_BACKEND_START_NAMESPACE
  35. // -----------------------------------------------------------------------
  36. struct PluginAudioPort {
  37. uint32_t rindex;
  38. CarlaEngineAudioPort* port;
  39. PluginAudioPort()
  40. : rindex(0),
  41. port(nullptr) {}
  42. ~PluginAudioPort()
  43. {
  44. CARLA_ASSERT(port == nullptr);
  45. }
  46. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginAudioPort)
  47. };
  48. struct PluginAudioData {
  49. uint32_t count;
  50. PluginAudioPort* ports;
  51. PluginAudioData()
  52. : count(0),
  53. ports(nullptr) {}
  54. ~PluginAudioData()
  55. {
  56. CARLA_ASSERT(ports == nullptr);
  57. }
  58. void createNew(const size_t count)
  59. {
  60. CARLA_ASSERT(ports == nullptr);
  61. if (ports == nullptr)
  62. ports = new PluginAudioPort[count];
  63. }
  64. void free()
  65. {
  66. CARLA_ASSERT(ports != nullptr);
  67. if (ports != nullptr)
  68. {
  69. delete[] ports;
  70. ports = nullptr;
  71. }
  72. }
  73. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginAudioData)
  74. };
  75. // -----------------------------------------------------------------------
  76. struct PluginEventData {
  77. CarlaEngineEventPort* portIn;
  78. CarlaEngineEventPort* portOut;
  79. PluginEventData()
  80. : portIn(nullptr),
  81. portOut(nullptr) {}
  82. ~PluginEventData()
  83. {
  84. CARLA_ASSERT(portIn == nullptr);
  85. CARLA_ASSERT(portOut == nullptr);
  86. }
  87. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginEventData)
  88. };
  89. // -----------------------------------------------------------------------
  90. struct PluginParameterData {
  91. uint32_t count;
  92. ParameterData* data;
  93. ParameterRanges* ranges;
  94. PluginParameterData()
  95. : count(0),
  96. data(nullptr),
  97. ranges(nullptr) {}
  98. ~PluginParameterData()
  99. {
  100. CARLA_ASSERT(data == nullptr);
  101. CARLA_ASSERT(ranges == nullptr);
  102. }
  103. void createNew(const size_t count)
  104. {
  105. CARLA_ASSERT(data == nullptr);
  106. CARLA_ASSERT(ranges == nullptr);
  107. if (data == nullptr)
  108. data = new ParameterData[count];
  109. if (ranges == nullptr)
  110. ranges = new ParameterRanges[count];
  111. }
  112. void free()
  113. {
  114. CARLA_ASSERT(data != nullptr);
  115. CARLA_ASSERT(ranges != nullptr);
  116. if (data != nullptr)
  117. {
  118. delete[] data;
  119. data = nullptr;
  120. }
  121. if (ranges != nullptr)
  122. {
  123. delete[] ranges;
  124. ranges = nullptr;
  125. }
  126. }
  127. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginParameterData)
  128. };
  129. // -----------------------------------------------------------------------
  130. typedef const char* ProgramName;
  131. struct PluginProgramData {
  132. uint32_t count;
  133. int32_t current;
  134. ProgramName* names;
  135. PluginProgramData()
  136. : count(0),
  137. current(-1),
  138. names(nullptr) {}
  139. ~PluginProgramData()
  140. {
  141. CARLA_ASSERT(names == nullptr);
  142. }
  143. void createNew(const size_t count)
  144. {
  145. CARLA_ASSERT(names == nullptr);
  146. if (names == nullptr)
  147. names = new ProgramName[count];
  148. }
  149. void free()
  150. {
  151. CARLA_ASSERT(names != nullptr);
  152. if (names != nullptr)
  153. {
  154. delete[] names;
  155. names = nullptr;
  156. }
  157. }
  158. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginProgramData)
  159. };
  160. struct PluginMidiProgramData {
  161. uint32_t count;
  162. int32_t current;
  163. MidiProgramData* data;
  164. PluginMidiProgramData()
  165. : count(0),
  166. current(-1),
  167. data(nullptr) {}
  168. ~PluginMidiProgramData()
  169. {
  170. CARLA_ASSERT(data == nullptr);
  171. }
  172. void createNew(const size_t count)
  173. {
  174. CARLA_ASSERT(data == nullptr);
  175. if (data == nullptr)
  176. data = new MidiProgramData[count];
  177. }
  178. void free()
  179. {
  180. CARLA_ASSERT(data != nullptr);
  181. if (data != nullptr)
  182. {
  183. delete[] data;
  184. data = nullptr;
  185. }
  186. }
  187. const MidiProgramData& getCurrent()
  188. {
  189. return data[current];
  190. }
  191. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(PluginMidiProgramData)
  192. };
  193. // -----------------------------------------------------------------------
  194. struct PluginPostRtEvent {
  195. PluginPostRtEventType type;
  196. int32_t value1;
  197. int32_t value2;
  198. double value3;
  199. PluginPostRtEvent()
  200. : type(kPluginPostRtEventNull),
  201. value1(-1),
  202. value2(-1),
  203. value3(0.0) {}
  204. CARLA_DECLARE_NON_COPY_STRUCT(PluginPostRtEvent)
  205. };
  206. // -----------------------------------------------------------------------
  207. struct ExternalMidiNote {
  208. int8_t channel; // invalid = -1
  209. uint8_t note;
  210. uint8_t velo;
  211. ExternalMidiNote()
  212. : channel(-1),
  213. note(0),
  214. velo(0) {}
  215. CARLA_DECLARE_NON_COPY_STRUCT(ExternalMidiNote)
  216. };
  217. // -----------------------------------------------------------------------
  218. const unsigned int PLUGIN_OPTION2_HAS_MIDI_IN = 0x1;
  219. const unsigned int PLUGIN_OPTION2_HAS_MIDI_OUT = 0x2;
  220. struct CarlaPluginProtectedData {
  221. unsigned short id;
  222. CarlaEngine* const engine;
  223. CarlaEngineClient* client;
  224. unsigned int hints;
  225. unsigned int options;
  226. unsigned int options2;
  227. bool active;
  228. bool activeBefore;
  229. bool enabled;
  230. void* lib;
  231. const char* name;
  232. const char* filename;
  233. // misc
  234. int8_t ctrlInChannel;
  235. uint32_t latency;
  236. float** latencyBuffers;
  237. // data
  238. PluginAudioData audioIn;
  239. PluginAudioData audioOut;
  240. PluginEventData event;
  241. PluginParameterData param;
  242. PluginProgramData prog;
  243. PluginMidiProgramData midiprog;
  244. NonRtList<CustomData> custom;
  245. struct ExternalNotes {
  246. CarlaMutex mutex;
  247. RtList<ExternalMidiNote> data;
  248. ExternalNotes()
  249. : data(32, 512) {}
  250. } extNotes;
  251. struct PostRtEvents {
  252. CarlaMutex mutex;
  253. RtList<PluginPostRtEvent> data;
  254. PostRtEvents()
  255. : data(152, 512) {}
  256. void append(const PluginPostRtEvent& event)
  257. {
  258. data.append(event);
  259. }
  260. } postRtEvents;
  261. struct PostProc {
  262. double dryWet;
  263. double volume;
  264. double balanceLeft;
  265. double balanceRight;
  266. double panning;
  267. PostProc()
  268. : dryWet(1.0),
  269. volume(1.0),
  270. balanceLeft(-1.0),
  271. balanceRight(1.0),
  272. panning(0.0) {}
  273. } postProc;
  274. struct OSC {
  275. CarlaOscData data;
  276. CarlaPluginThread* thread;
  277. OSC()
  278. : thread(nullptr) {}
  279. } osc;
  280. CarlaPluginProtectedData(CarlaEngine* const engine_, const unsigned short id_)
  281. : id(id_),
  282. engine(engine_),
  283. client(nullptr),
  284. hints(0x0),
  285. options(0x0),
  286. options2(0x0),
  287. active(false),
  288. activeBefore(false),
  289. enabled(false),
  290. lib(nullptr),
  291. name(nullptr),
  292. filename(nullptr),
  293. ctrlInChannel(-1),
  294. latency(0),
  295. latencyBuffers(nullptr) {}
  296. CarlaPluginProtectedData() = delete;
  297. CARLA_LEAK_DETECTOR(CarlaPluginProtectedData)
  298. };
  299. // -----------------------------------------------------------------------
  300. CARLA_BACKEND_END_NAMESPACE
  301. #endif // __CARLA_PLUGIN_INTERNAL_HPP__
  302. // common includes
  303. //#include <cmath>
  304. //#include <vector>
  305. //#include <QtCore/QMutex>
  306. //#include <QtGui/QMainWindow>
  307. //#ifdef Q_WS_X11
  308. //# include <QtGui/QX11EmbedContainer>
  309. //typedef QX11EmbedContainer GuiContainer;
  310. //#else
  311. //# include <QtGui/QWidget>
  312. //typedef QWidget GuiContainer;
  313. //#endif
  314. #if 0
  315. // -------------------------------------------------------------------
  316. // Extra
  317. ExternalMidiNote extMidiNotes[MAX_MIDI_EVENTS];
  318. // -------------------------------------------------------------------
  319. // Utilities
  320. static double fixParameterValue(double& value, const ParameterRanges& ranges)
  321. {
  322. if (value < ranges.min)
  323. value = ranges.min;
  324. else if (value > ranges.max)
  325. value = ranges.max;
  326. return value;
  327. }
  328. static float fixParameterValue(float& value, const ParameterRanges& ranges)
  329. {
  330. if (value < ranges.min)
  331. value = ranges.min;
  332. else if (value > ranges.max)
  333. value = ranges.max;
  334. return value;
  335. }
  336. friend class CarlaEngine; // FIXME
  337. friend class CarlaEngineJack;
  338. #endif
  339. #if 0
  340. // -------------------------------------------------------------------
  341. /*!
  342. * \class ScopedDisabler
  343. *
  344. * \brief Carla plugin scoped disabler
  345. *
  346. * This is a handy class that temporarily disables a plugin during a function scope.\n
  347. * It should be used when the plugin needs reload or state change, something like this:
  348. * \code
  349. * {
  350. * const CarlaPlugin::ScopedDisabler m(plugin);
  351. * plugin->setChunkData(data);
  352. * }
  353. * \endcode
  354. */
  355. class ScopedDisabler
  356. {
  357. public:
  358. /*!
  359. * Disable plugin \a plugin if \a disable is true.
  360. * The plugin is re-enabled in the deconstructor of this class if \a disable is true.
  361. *
  362. * \param plugin The plugin to disable
  363. * \param disable Wherever to disable the plugin or not, true by default
  364. */
  365. ScopedDisabler(CarlaPlugin* const plugin, const bool disable = true)
  366. : m_plugin(plugin),
  367. m_disable(disable)
  368. {
  369. if (m_disable)
  370. {
  371. m_plugin->engineProcessLock();
  372. m_plugin->setEnabled(false);
  373. m_plugin->engineProcessUnlock();
  374. }
  375. }
  376. ~ScopedDisabler()
  377. {
  378. if (m_disable)
  379. {
  380. m_plugin->engineProcessLock();
  381. m_plugin->setEnabled(true);
  382. m_plugin->engineProcessUnlock();
  383. }
  384. }
  385. private:
  386. CarlaPlugin* const m_plugin;
  387. const bool m_disable;
  388. };
  389. /*!
  390. * \class CarlaPluginGUI
  391. *
  392. * \brief Carla Backend gui plugin class
  393. *
  394. * \see CarlaPlugin
  395. */
  396. class CarlaPluginGUI : public QMainWindow
  397. {
  398. public:
  399. /*!
  400. * \class Callback
  401. *
  402. * \brief Carla plugin GUI callback
  403. */
  404. class Callback
  405. {
  406. public:
  407. virtual ~Callback() {}
  408. virtual void guiClosedCallback() = 0;
  409. };
  410. // -------------------------------------------------------------------
  411. // Constructor and destructor
  412. /*!
  413. * TODO
  414. */
  415. CarlaPluginGUI(QWidget* const parent, Callback* const callback);
  416. /*!
  417. * TODO
  418. */
  419. ~CarlaPluginGUI();
  420. // -------------------------------------------------------------------
  421. // Get data
  422. /*!
  423. * TODO
  424. */
  425. GuiContainer* getContainer() const;
  426. /*!
  427. * TODO
  428. */
  429. WId getWinId() const;
  430. // -------------------------------------------------------------------
  431. // Set data
  432. /*!
  433. * TODO
  434. */
  435. void setNewSize(const int width, const int height);
  436. /*!
  437. * TODO
  438. */
  439. void setResizable(const bool resizable);
  440. /*!
  441. * TODO
  442. */
  443. void setTitle(const char* const title);
  444. /*!
  445. * TODO
  446. */
  447. void setVisible(const bool yesNo);
  448. // -------------------------------------------------------------------
  449. private:
  450. Callback* const m_callback;
  451. GuiContainer* m_container;
  452. QByteArray m_geometry;
  453. bool m_resizable;
  454. void hideEvent(QHideEvent* const event);
  455. void closeEvent(QCloseEvent* const event);
  456. };
  457. #endif