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.

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