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.

477 lines
12KB

  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. // -----------------------------------------------------------------------