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.

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