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.

434 lines
11KB

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