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.

459 lines
12KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2014 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 "DistrhoPluginInternal.hpp"
  17. #if DISTRHO_PLUGIN_HAS_UI
  18. # include "DistrhoUIInternal.hpp"
  19. #endif
  20. #include "CarlaNative.hpp"
  21. // -----------------------------------------------------------------------
  22. START_NAMESPACE_DISTRHO
  23. #if DISTRHO_PLUGIN_HAS_UI
  24. // -----------------------------------------------------------------------
  25. // Carla UI
  26. #if ! DISTRHO_PLUGIN_WANT_STATE
  27. static const setStateFunc setStateCallback = nullptr;
  28. #endif
  29. #if ! DISTRHO_PLUGIN_IS_SYNTH
  30. static const sendNoteFunc sendNoteCallback = nullptr;
  31. #endif
  32. class UICarla
  33. {
  34. public:
  35. UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin)
  36. : fHost(host),
  37. fPlugin(plugin),
  38. fUI(this, 0, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback)
  39. {
  40. fUI.setTitle(host->uiName);
  41. if (host->uiParentId != 0)
  42. fUI.setTransientWinId(host->uiParentId);
  43. }
  44. // ---------------------------------------------
  45. void carla_show(const bool yesNo)
  46. {
  47. fUI.setVisible(yesNo);
  48. }
  49. void carla_idle()
  50. {
  51. fUI.idle();
  52. }
  53. void carla_setParameterValue(const uint32_t index, const float value)
  54. {
  55. fUI.parameterChanged(index, value);
  56. }
  57. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  58. void carla_setMidiProgram(const uint32_t realProgram)
  59. {
  60. fUI.programChanged(realProgram);
  61. }
  62. #endif
  63. #if DISTRHO_PLUGIN_WANT_STATE
  64. void carla_setCustomData(const char* const key, const char* const value)
  65. {
  66. fUI.stateChanged(key, value);
  67. }
  68. #endif
  69. void carla_setUiTitle(const char* const uiTitle)
  70. {
  71. fUI.setTitle(uiTitle);
  72. }
  73. // ---------------------------------------------
  74. protected:
  75. void handleEditParameter(const uint32_t, const bool)
  76. {
  77. // TODO
  78. }
  79. void handleSetParameterValue(const uint32_t rindex, const float value)
  80. {
  81. fHost->ui_parameter_changed(fHost->handle, rindex, value);
  82. }
  83. void handleSetState(const char* const key, const char* const value)
  84. {
  85. fHost->ui_custom_data_changed(fHost->handle, key, value);
  86. }
  87. void handleSendNote(const uint8_t, const uint8_t, const uint8_t)
  88. {
  89. // TODO
  90. }
  91. void handleUiResize(const unsigned int width, const unsigned int height)
  92. {
  93. fUI.setSize(width, height);
  94. }
  95. // ---------------------------------------------
  96. private:
  97. // Plugin stuff
  98. const NativeHostDescriptor* const fHost;
  99. PluginExporter* const fPlugin;
  100. // UI
  101. UIExporter fUI;
  102. // ---------------------------------------------
  103. // Callbacks
  104. #define handlePtr ((UICarla*)ptr)
  105. static void editParameterCallback(void* ptr, uint32_t index, bool started)
  106. {
  107. handlePtr->handleEditParameter(index, started);
  108. }
  109. static void setParameterCallback(void* ptr, uint32_t rindex, float value)
  110. {
  111. handlePtr->handleSetParameterValue(rindex, value);
  112. }
  113. #if DISTRHO_PLUGIN_WANT_STATE
  114. static void setStateCallback(void* ptr, const char* key, const char* value)
  115. {
  116. handlePtr->handleSetState(key, value);
  117. }
  118. #endif
  119. #if DISTRHO_PLUGIN_IS_SYNTH
  120. static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
  121. {
  122. handlePtr->handleSendNote(channel, note, velocity);
  123. }
  124. #endif
  125. static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height)
  126. {
  127. handlePtr->handleUiResize(width, height);
  128. }
  129. #undef handlePtr
  130. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UICarla)
  131. };
  132. #endif // DISTRHO_PLUGIN_HAS_UI
  133. // -----------------------------------------------------------------------
  134. // Carla Plugin
  135. class PluginCarla : public NativePluginClass
  136. {
  137. public:
  138. PluginCarla(const NativeHostDescriptor* const host)
  139. : NativePluginClass(host)
  140. {
  141. #if DISTRHO_PLUGIN_HAS_UI
  142. fUiPtr = nullptr;
  143. #endif
  144. }
  145. ~PluginCarla() override
  146. {
  147. #if DISTRHO_PLUGIN_HAS_UI
  148. if (fUiPtr != nullptr)
  149. {
  150. delete fUiPtr;
  151. fUiPtr = nullptr;
  152. }
  153. #endif
  154. }
  155. protected:
  156. // -------------------------------------------------------------------
  157. // Plugin parameter calls
  158. uint32_t getParameterCount() const override
  159. {
  160. return fPlugin.getParameterCount();
  161. }
  162. const NativeParameter* getParameterInfo(const uint32_t index) const override
  163. {
  164. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
  165. static NativeParameter param;
  166. // reset
  167. param.hints = ::PARAMETER_IS_ENABLED;
  168. param.scalePointCount = 0;
  169. param.scalePoints = nullptr;
  170. {
  171. int nativeParamHints = ::PARAMETER_IS_ENABLED;
  172. const uint32_t paramHints = fPlugin.getParameterHints(index);
  173. if (paramHints & PARAMETER_IS_AUTOMABLE)
  174. nativeParamHints |= ::PARAMETER_IS_AUTOMABLE;
  175. if (paramHints & PARAMETER_IS_BOOLEAN)
  176. nativeParamHints |= ::PARAMETER_IS_BOOLEAN;
  177. if (paramHints & PARAMETER_IS_INTEGER)
  178. nativeParamHints |= ::PARAMETER_IS_INTEGER;
  179. if (paramHints & PARAMETER_IS_LOGARITHMIC)
  180. nativeParamHints |= ::PARAMETER_IS_LOGARITHMIC;
  181. if (paramHints & PARAMETER_IS_OUTPUT)
  182. nativeParamHints |= ::PARAMETER_IS_OUTPUT;
  183. param.hints = static_cast<NativeParameterHints>(nativeParamHints);
  184. }
  185. param.name = fPlugin.getParameterName(index);
  186. param.unit = fPlugin.getParameterUnit(index);
  187. {
  188. const ParameterRanges& ranges(fPlugin.getParameterRanges(index));
  189. param.ranges.def = ranges.def;
  190. param.ranges.min = ranges.min;
  191. param.ranges.max = ranges.max;
  192. }
  193. return &param;
  194. }
  195. float getParameterValue(const uint32_t index) const override
  196. {
  197. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f);
  198. return fPlugin.getParameterValue(index);
  199. }
  200. // -------------------------------------------------------------------
  201. // Plugin midi-program calls
  202. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  203. uint32_t getMidiProgramCount() const override
  204. {
  205. return fPlugin.getProgramCount();
  206. }
  207. const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const override
  208. {
  209. CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr);
  210. static NativeMidiProgram midiProgram;
  211. midiProgram.bank = index / 128;
  212. midiProgram.program = index % 128;
  213. midiProgram.name = fPlugin.getProgramName(index);
  214. return &midiProgram;
  215. }
  216. #endif
  217. // -------------------------------------------------------------------
  218. // Plugin state calls
  219. void setParameterValue(const uint32_t index, const float value) override
  220. {
  221. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  222. fPlugin.setParameterValue(index, value);
  223. }
  224. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  225. void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
  226. {
  227. const uint32_t realProgram(bank * 128 + program);
  228. CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);
  229. fPlugin.setProgram(realProgram);
  230. }
  231. #endif
  232. #if DISTRHO_PLUGIN_WANT_STATE
  233. void setCustomData(const char* const key, const char* const value) override
  234. {
  235. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  236. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  237. fPlugin.setState(key, value);
  238. }
  239. #endif
  240. // -------------------------------------------------------------------
  241. // Plugin process calls
  242. void activate() override
  243. {
  244. fPlugin.activate();
  245. }
  246. void deactivate() override
  247. {
  248. fPlugin.deactivate();
  249. }
  250. #if DISTRHO_PLUGIN_IS_SYNTH
  251. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
  252. {
  253. MidiEvent realMidiEvents[midiEventCount];
  254. for (uint32_t i=0; i < midiEventCount; ++i)
  255. {
  256. const NativeMidiEvent& midiEvent(midiEvents[i]);
  257. MidiEvent& realMidiEvent(realMidiEvents[i]);
  258. realMidiEvent.frame = midiEvent.time;
  259. realMidiEvent.size = midiEvent.size;
  260. carla_copy<uint8_t>(realMidiEvent.buf, midiEvent.data, midiEvent.size);
  261. }
  262. fPlugin.run(inBuffer, outBuffer, frames, realMidiEvents, midiEventCount);
  263. }
  264. #else
  265. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override
  266. {
  267. fPlugin.run(inBuffer, outBuffer, frames);
  268. }
  269. #endif
  270. // -------------------------------------------------------------------
  271. // Plugin UI calls
  272. #if DISTRHO_PLUGIN_HAS_UI
  273. void uiShow(const bool show) override
  274. {
  275. if (show)
  276. createUiIfNeeded();
  277. if (fUiPtr != nullptr)
  278. fUiPtr->carla_show(show);
  279. }
  280. void uiIdle() override
  281. {
  282. CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
  283. fUiPtr->carla_idle();
  284. }
  285. void uiSetParameterValue(const uint32_t index, const float value) override
  286. {
  287. CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
  288. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  289. fUiPtr->carla_setParameterValue(index, value);
  290. }
  291. # if DISTRHO_PLUGIN_WANT_PROGRAMS
  292. void uiSetMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
  293. {
  294. CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
  295. const uint32_t realProgram(bank * 128 + program);
  296. CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);
  297. fUiPtr->carla_setMidiProgram(realProgram);
  298. }
  299. # endif
  300. # if DISTRHO_PLUGIN_WANT_STATE
  301. void uiSetCustomData(const char* const key, const char* const value) override
  302. {
  303. CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
  304. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  305. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  306. fUiPtr->carla_setCustomData(key, value);
  307. }
  308. # endif
  309. #endif
  310. // -------------------------------------------------------------------
  311. // Plugin dispatcher calls
  312. void bufferSizeChanged(const uint32_t bufferSize) override
  313. {
  314. fPlugin.setBufferSize(bufferSize, true);
  315. }
  316. void sampleRateChanged(const double sampleRate) override
  317. {
  318. fPlugin.setSampleRate(sampleRate, true);
  319. }
  320. #if DISTRHO_PLUGIN_HAS_UI
  321. void uiNameChanged(const char* const uiName) override
  322. {
  323. CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
  324. fUiPtr->carla_setUiTitle(uiName);
  325. }
  326. #endif
  327. // -------------------------------------------------------------------
  328. private:
  329. PluginExporter fPlugin;
  330. #if DISTRHO_PLUGIN_HAS_UI
  331. // UI
  332. UICarla* fUiPtr;
  333. void createUiIfNeeded()
  334. {
  335. if (fUiPtr == nullptr)
  336. {
  337. d_lastUiSampleRate = getSampleRate();
  338. fUiPtr = new UICarla(getHostHandle(), &fPlugin);
  339. }
  340. }
  341. #endif
  342. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginCarla)
  343. // -------------------------------------------------------------------
  344. public:
  345. static NativePluginHandle _instantiate(const NativeHostDescriptor* host)
  346. {
  347. d_lastBufferSize = host->get_buffer_size(host->handle);
  348. d_lastSampleRate = host->get_sample_rate(host->handle);
  349. return new PluginCarla(host);
  350. }
  351. static void _cleanup(NativePluginHandle handle)
  352. {
  353. delete (PluginCarla*)handle;
  354. }
  355. };
  356. END_NAMESPACE_DISTRHO
  357. // -----------------------------------------------------------------------