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.

607 lines
13KB

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