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.

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