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.

479 lines
12KB

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