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.

627 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 uint32_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 uint32_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>::Pool dataPool;
  318. RtList<ExternalMidiNote> data;
  319. ExternalNotes()
  320. : dataPool(32, 512),
  321. data(&dataPool) {}
  322. void append(const ExternalMidiNote& note)
  323. {
  324. data.append_sleepy(note);
  325. }
  326. } extNotes;
  327. struct PostRtEvents {
  328. CarlaMutex mutex;
  329. RtList<PluginPostRtEvent>::Pool dataPool;
  330. RtList<PluginPostRtEvent> data;
  331. RtList<PluginPostRtEvent> dataPendingRT;
  332. PostRtEvents()
  333. : dataPool(MIN_RT_EVENTS, MAX_RT_EVENTS),
  334. data(&dataPool),
  335. dataPendingRT(&dataPool) {}
  336. ~PostRtEvents()
  337. {
  338. clear();
  339. }
  340. void appendRT(const PluginPostRtEvent& event)
  341. {
  342. dataPendingRT.append(event);
  343. }
  344. void trySplice()
  345. {
  346. if (mutex.tryLock())
  347. {
  348. dataPendingRT.splice(data, true);
  349. mutex.unlock();
  350. }
  351. }
  352. void clear()
  353. {
  354. mutex.lock();
  355. data.clear();
  356. dataPendingRT.clear();
  357. mutex.unlock();
  358. }
  359. //void appendNonRT(const PluginPostRtEvent& event)
  360. //{
  361. // data.append_sleepy(event);
  362. //}
  363. } postRtEvents;
  364. struct PostProc {
  365. float dryWet;
  366. float volume;
  367. float balanceLeft;
  368. float balanceRight;
  369. float panning;
  370. PostProc()
  371. : dryWet(1.0f),
  372. volume(1.0f),
  373. balanceLeft(-1.0f),
  374. balanceRight(1.0f),
  375. panning(0.0f) {}
  376. } postProc;
  377. struct OSC {
  378. CarlaOscData data;
  379. CarlaPluginThread* thread;
  380. OSC()
  381. : thread(nullptr) {}
  382. } osc;
  383. CarlaPluginProtectedData(CarlaEngine* const engine_, const unsigned short id_)
  384. : id(id_),
  385. engine(engine_),
  386. client(nullptr),
  387. gui(nullptr),
  388. hints(0x0),
  389. options(0x0),
  390. options2(0x0),
  391. active(false),
  392. activeBefore(false),
  393. enabled(false),
  394. lib(nullptr),
  395. ctrlInChannel(-1),
  396. latency(0),
  397. latencyBuffers(nullptr) {}
  398. CarlaPluginProtectedData() = delete;
  399. CarlaPluginProtectedData(CarlaPluginProtectedData&) = delete;
  400. CarlaPluginProtectedData(const CarlaPluginProtectedData&) = delete;
  401. CARLA_LEAK_DETECTOR(CarlaPluginProtectedData)
  402. };
  403. // -----------------------------------------------------------------------
  404. CARLA_BACKEND_END_NAMESPACE
  405. #endif // __CARLA_PLUGIN_INTERNAL_HPP__
  406. // common includes
  407. //#include <cmath>
  408. //#include <vector>
  409. //#include <QtCore/QMutex>
  410. //#include <QtGui/QMainWindow>
  411. //#ifdef Q_WS_X11
  412. //# include <QtGui/QX11EmbedContainer>
  413. //typedef QX11EmbedContainer GuiContainer;
  414. //#else
  415. //# include <QtGui/QWidget>
  416. //typedef QWidget GuiContainer;
  417. //#endif
  418. #if 0
  419. /*!
  420. * \class CarlaPluginGUI
  421. *
  422. * \brief Carla Backend gui plugin class
  423. *
  424. * \see CarlaPlugin
  425. */
  426. class CarlaPluginGUI : public QMainWindow
  427. {
  428. public:
  429. /*!
  430. * \class Callback
  431. *
  432. * \brief Carla plugin GUI callback
  433. */
  434. class Callback
  435. {
  436. public:
  437. virtual ~Callback() {}
  438. virtual void guiClosedCallback() = 0;
  439. };
  440. // -------------------------------------------------------------------
  441. // Constructor and destructor
  442. /*!
  443. * TODO
  444. */
  445. CarlaPluginGUI(QWidget* const parent, Callback* const callback);
  446. /*!
  447. * TODO
  448. */
  449. ~CarlaPluginGUI();
  450. // -------------------------------------------------------------------
  451. // Get data
  452. /*!
  453. * TODO
  454. */
  455. GuiContainer* getContainer() const;
  456. /*!
  457. * TODO
  458. */
  459. WId getWinId() const;
  460. // -------------------------------------------------------------------
  461. // Set data
  462. /*!
  463. * TODO
  464. */
  465. void setNewSize(const int width, const int height);
  466. /*!
  467. * TODO
  468. */
  469. void setResizable(const bool resizable);
  470. /*!
  471. * TODO
  472. */
  473. void setTitle(const char* const title);
  474. /*!
  475. * TODO
  476. */
  477. void setVisible(const bool yesNo);
  478. // -------------------------------------------------------------------
  479. private:
  480. Callback* const m_callback;
  481. GuiContainer* m_container;
  482. QByteArray m_geometry;
  483. bool m_resizable;
  484. void hideEvent(QHideEvent* const event);
  485. void closeEvent(QCloseEvent* const event);
  486. };
  487. #endif