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.

DistrhoPluginCarla.cpp 12KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * DISTRHO Plugin Toolkit (DPT)
  3. * Copyright (C) 2012-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 Lesser General Public
  7. * License as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * For a full copy of the license see the LGPL.txt file
  15. */
  16. #include "carla_native.hpp"
  17. #include "carla_utils.hpp"
  18. #include <QtGui/QMainWindow>
  19. #include "DistrhoPluginMain.cpp"
  20. #if DISTRHO_PLUGIN_HAS_UI
  21. # include "DistrhoUIMain.cpp"
  22. #endif
  23. // -------------------------------------------------
  24. START_NAMESPACE_DISTRHO
  25. #if DISTRHO_PLUGIN_HAS_UI
  26. // -----------------------------------------------------------------------
  27. // Carla UI
  28. class UICarla : public QMainWindow
  29. {
  30. public:
  31. UICarla(const HostDescriptor* const host_, PluginInternal* const plugin_)
  32. : QMainWindow(nullptr),
  33. host(host_),
  34. plugin(plugin_),
  35. widget(this),
  36. ui(this, (intptr_t)widget.winId(), setParameterCallback, setStateCallback, uiEditParameterCallback, uiSendNoteCallback, uiResizeCallback)
  37. {
  38. setCentralWidget(&widget);
  39. setFixedSize(ui.getWidth(), ui.getHeight());
  40. setWindowTitle(DISTRHO_PLUGIN_NAME);
  41. }
  42. ~UICarla()
  43. {
  44. }
  45. // ---------------------------------------------
  46. void carla_show(const bool yesNo)
  47. {
  48. setVisible(yesNo);
  49. }
  50. void carla_idle()
  51. {
  52. ui.idle();
  53. }
  54. void carla_setParameterValue(const uint32_t index, const float value)
  55. {
  56. ui.parameterChanged(index, value);
  57. }
  58. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  59. void carla_setMidiProgram(const uint32_t realProgram)
  60. {
  61. ui.programChanged(realProgram);
  62. }
  63. # endif
  64. # if DISTRHO_PLUGIN_WANT_STATE
  65. void carla_setCustomData(const char* const key, const char* const value)
  66. {
  67. ui.stateChanged(key, value);
  68. }
  69. # endif
  70. // ---------------------------------------------
  71. protected:
  72. void setParameterValue(uint32_t rindex, float value)
  73. {
  74. host->ui_parameter_changed(host->handle, rindex, value);
  75. }
  76. # if DISTRHO_PLUGIN_WANT_STATE
  77. void setState(const char* key, const char* value)
  78. {
  79. host->ui_custom_data_changed(host->handle, key, value);
  80. }
  81. # endif
  82. void uiEditParameter(uint32_t, bool)
  83. {
  84. // TODO
  85. }
  86. # if DISTRHO_PLUGIN_IS_SYNTH
  87. void uiSendNote(bool, uint8_t, uint8_t, uint8_t)
  88. {
  89. // TODO
  90. }
  91. # endif
  92. void uiResize(int width, int height)
  93. {
  94. setFixedSize(width, height);
  95. }
  96. void closeEvent(QCloseEvent* event)
  97. {
  98. host->ui_closed(host->handle);
  99. // FIXME - ignore event?
  100. QMainWindow::closeEvent(event);
  101. }
  102. private:
  103. // Plugin stuff
  104. const HostDescriptor* const host;
  105. PluginInternal* const plugin;
  106. // Qt4 stuff
  107. QWidget widget;
  108. // UI
  109. UIInternal ui;
  110. // ---------------------------------------------
  111. // Callbacks
  112. static void setParameterCallback(void* ptr, uint32_t rindex, float value)
  113. {
  114. if (UICarla* _this_ = (UICarla*)ptr)
  115. _this_->setParameterValue(rindex, value);
  116. }
  117. static void setStateCallback(void* ptr, const char* key, const char* value)
  118. {
  119. # if DISTRHO_PLUGIN_WANT_STATE
  120. if (UICarla* _this_ = (UICarla*)ptr)
  121. _this_->setState(key, value);
  122. # else
  123. return;
  124. // unused
  125. Q_UNUSED(ptr);
  126. Q_UNUSED(key);
  127. Q_UNUSED(value);
  128. # endif
  129. }
  130. static void uiEditParameterCallback(void* ptr, uint32_t index, bool started)
  131. {
  132. if (UICarla* _this_ = (UICarla*)ptr)
  133. _this_->uiEditParameter(index, started);
  134. }
  135. static void uiSendNoteCallback(void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
  136. {
  137. # if DISTRHO_PLUGIN_IS_SYNTH
  138. if (UICarla* _this_ = (UICarla*)ptr)
  139. _this_->uiSendNote(onOff, channel, note, velocity);
  140. # else
  141. return;
  142. // unused
  143. Q_UNUSED(ptr);
  144. Q_UNUSED(onOff);
  145. Q_UNUSED(channel);
  146. Q_UNUSED(note);
  147. Q_UNUSED(velocity);
  148. # endif
  149. }
  150. static void uiResizeCallback(void* ptr, int width, int height)
  151. {
  152. if (UICarla* _this_ = (UICarla*)ptr)
  153. _this_->uiResize(width, height);
  154. }
  155. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UICarla)
  156. };
  157. #endif
  158. // -----------------------------------------------------------------------
  159. // Carla Plugin
  160. class PluginCarla : public PluginDescriptorClass
  161. {
  162. public:
  163. PluginCarla(const HostDescriptor* const host)
  164. : PluginDescriptorClass(host)
  165. {
  166. #if DISTRHO_PLUGIN_HAS_UI
  167. uiPtr = nullptr;
  168. #endif
  169. }
  170. ~PluginCarla()
  171. {
  172. #if DISTRHO_PLUGIN_HAS_UI
  173. uiPtr = nullptr;
  174. #endif
  175. }
  176. protected:
  177. // -------------------------------------------------------------------
  178. // Plugin parameter calls
  179. uint32_t getParameterCount()
  180. {
  181. return plugin.parameterCount();
  182. }
  183. const ::Parameter* getParameterInfo(const uint32_t index)
  184. {
  185. CARLA_ASSERT(index < getParameterCount());
  186. static ::Parameter param;
  187. // reset
  188. param.hints = ::PARAMETER_IS_ENABLED;
  189. param.scalePointCount = 0;
  190. param.scalePoints = nullptr;
  191. {
  192. int nativeparamHints = 0;
  193. const uint32_t paramHints = plugin.parameterHints(index);
  194. if (paramHints & PARAMETER_IS_AUTOMABLE)
  195. nativeparamHints |= ::PARAMETER_IS_AUTOMABLE;
  196. if (paramHints & PARAMETER_IS_BOOLEAN)
  197. nativeparamHints |= ::PARAMETER_IS_BOOLEAN;
  198. if (paramHints & PARAMETER_IS_INTEGER)
  199. nativeparamHints |= ::PARAMETER_IS_INTEGER;
  200. if (paramHints & PARAMETER_IS_LOGARITHMIC)
  201. nativeparamHints |= ::PARAMETER_IS_LOGARITHMIC;
  202. if (paramHints & PARAMETER_IS_OUTPUT)
  203. nativeparamHints |= ::PARAMETER_IS_OUTPUT;
  204. param.hints = static_cast<ParameterHints>(nativeparamHints);
  205. }
  206. param.name = plugin.parameterName(index);
  207. param.unit = plugin.parameterUnit(index);
  208. {
  209. const ParameterRanges& ranges(plugin.parameterRanges(index));
  210. param.ranges.def = ranges.def;
  211. param.ranges.min = ranges.min;
  212. param.ranges.max = ranges.max;
  213. param.ranges.step = ranges.step;
  214. param.ranges.stepSmall = ranges.stepSmall;
  215. param.ranges.stepLarge = ranges.stepLarge;
  216. }
  217. return &param;
  218. }
  219. float getParameterValue(const uint32_t index)
  220. {
  221. CARLA_ASSERT(index < getParameterCount());
  222. return plugin.parameterValue(index);
  223. }
  224. // getParameterText unused
  225. // -------------------------------------------------------------------
  226. // Plugin midi-program calls
  227. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  228. virtual uint32_t getMidiProgramCount()
  229. {
  230. return plugin.programCount();
  231. }
  232. virtual const ::MidiProgram* getMidiProgramInfo(const uint32_t index)
  233. {
  234. CARLA_ASSERT(index < getMidiProgramCount());
  235. if (index >= plugin.programCount())
  236. return nullptr;
  237. static ::MidiProgram midiProgram;
  238. midiProgram.bank = index / 128;
  239. midiProgram.program = index % 128;
  240. midiProgram.name = plugin.programName(index);
  241. return &midiProgram;
  242. }
  243. #endif
  244. // -------------------------------------------------------------------
  245. // Plugin state calls
  246. void setParameterValue(const uint32_t index, const float value)
  247. {
  248. CARLA_ASSERT(index < getParameterCount());
  249. plugin.setParameterValue(index, value);
  250. }
  251. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  252. void setMidiProgram(const uint32_t bank, const uint32_t program)
  253. {
  254. const uint32_t realProgram = bank * 128 + program;
  255. if (realProgram >= plugin.programCount())
  256. return;
  257. plugin.setProgram(realProgram);
  258. }
  259. #endif
  260. #if DISTRHO_PLUGIN_WANT_STATE
  261. void setCustomData(const char* const key, const char* const value)
  262. {
  263. CARLA_ASSERT(key);
  264. CARLA_ASSERT(value);
  265. plugin.setState(key, value);
  266. }
  267. #endif
  268. // -------------------------------------------------------------------
  269. // Plugin process calls
  270. void activate()
  271. {
  272. plugin.activate();
  273. }
  274. void deactivate()
  275. {
  276. plugin.deactivate();
  277. }
  278. #if DISTRHO_PLUGIN_IS_SYNTH
  279. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const ::MidiEvent* const midiEvents)
  280. {
  281. uint32_t i;
  282. for (i=0; i < midiEventCount && i < MAX_MIDI_EVENTS; i++)
  283. {
  284. const ::MidiEvent* const midiEvent = &midiEvents[i];
  285. MidiEvent* const realMidiEvent = &realMidiEvents[i];
  286. realMidiEvent->buffer[0] = midiEvent->data[0];
  287. realMidiEvent->buffer[1] = midiEvent->data[1];
  288. realMidiEvent->buffer[2] = midiEvent->data[2];
  289. realMidiEvent->frame = midiEvent->time;
  290. }
  291. plugin.run(inBuffer, outBuffer, frames, i, realMidiEvents);
  292. }
  293. #else
  294. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t, const ::MidiEvent* const)
  295. {
  296. plugin.run(inBuffer, outBuffer, frames, 0, nullptr);
  297. }
  298. #endif
  299. // -------------------------------------------------------------------
  300. // Plugin UI calls
  301. #if DISTRHO_PLUGIN_HAS_UI
  302. void uiShow(const bool show)
  303. {
  304. if (show)
  305. createUiIfNeeded();
  306. if (uiPtr != nullptr)
  307. uiPtr->carla_show(show);
  308. }
  309. void uiIdle()
  310. {
  311. CARLA_ASSERT(uiPtr);
  312. if (uiPtr != nullptr)
  313. uiPtr->carla_idle();
  314. }
  315. void uiSetParameterValue(const uint32_t index, const float value)
  316. {
  317. CARLA_ASSERT(uiPtr);
  318. CARLA_ASSERT(index < getParameterCount());
  319. if (uiPtr != nullptr)
  320. uiPtr->carla_setParameterValue(index, value);
  321. }
  322. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  323. void uiSetMidiProgram(const uint32_t bank, const uint32_t program)
  324. {
  325. CARLA_ASSERT(uiPtr);
  326. uint32_t realProgram = bank * 128 + program;
  327. if (realProgram >= plugin.programCount())
  328. return;
  329. if (uiPtr != nullptr)
  330. uiPtr->carla_setMidiProgram(realProgram);
  331. }
  332. # endif
  333. # if DISTRHO_PLUGIN_WANT_STATE
  334. void uiSetCustomData(const char* const key, const char* const value)
  335. {
  336. CARLA_ASSERT(uiPtr);
  337. CARLA_ASSERT(key);
  338. CARLA_ASSERT(value);
  339. if (uiPtr != nullptr)
  340. uiPtr->carla_setCustomData(key, value);
  341. }
  342. # endif
  343. #endif
  344. // -------------------------------------------------------------------
  345. private:
  346. PluginInternal plugin;
  347. #if DISTRHO_PLUGIN_IS_SYNTH
  348. MidiEvent realMidiEvents[MAX_MIDI_EVENTS];
  349. #endif
  350. #if DISTRHO_PLUGIN_HAS_UI
  351. // UI
  352. ScopedPointer<UICarla> uiPtr;
  353. void createUiIfNeeded()
  354. {
  355. if (uiPtr == nullptr)
  356. {
  357. d_lastUiSampleRate = getSampleRate();
  358. uiPtr = new UICarla(getHostHandle(), &plugin);
  359. }
  360. }
  361. #endif
  362. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginCarla)
  363. // -------------------------------------------------------------------
  364. public:
  365. static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host)
  366. {
  367. d_lastBufferSize = host->get_buffer_size(host->handle);
  368. d_lastSampleRate = host->get_sample_rate(host->handle);
  369. return new PluginCarla(host);
  370. }
  371. static void _cleanup(PluginHandle handle)
  372. {
  373. delete (PluginCarla*)handle;
  374. }
  375. };
  376. END_NAMESPACE_DISTRHO
  377. // -----------------------------------------------------------------------