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.

327 lines
10KB

  1. /*
  2. * DISTRHO Ildaeil Plugin
  3. * Copyright (C) 2021 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 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 GNU General Public License see the LICENSE file.
  16. */
  17. #include "CarlaNativePlugin.h"
  18. #include "DistrhoPlugin.hpp"
  19. #include "DistrhoUI.hpp"
  20. START_NAMESPACE_DISTRHO
  21. // -----------------------------------------------------------------------------------------------------------
  22. static uint32_t host_get_buffer_size(NativeHostHandle);
  23. static double host_get_sample_rate(NativeHostHandle);
  24. static bool host_is_offline(NativeHostHandle);
  25. static const NativeTimeInfo* host_get_time_info(NativeHostHandle handle);
  26. static bool host_write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event);
  27. static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt);
  28. // -----------------------------------------------------------------------------------------------------------
  29. class IldaeilPlugin : public Plugin
  30. {
  31. public:
  32. const NativePluginDescriptor* fCarlaPluginDescriptor;
  33. NativePluginHandle fCarlaPluginHandle;
  34. NativeHostDescriptor fCarlaHostDescriptor;
  35. CarlaHostHandle fCarlaHostHandle;
  36. mutable NativeTimeInfo fCarlaTimeInfo;
  37. UI* fUI;
  38. void setUI(UI* const ui)
  39. {
  40. fUI = ui;
  41. }
  42. IldaeilPlugin()
  43. : Plugin(0, 0, 0),
  44. fCarlaPluginDescriptor(nullptr),
  45. fCarlaPluginHandle(nullptr),
  46. fCarlaHostHandle(nullptr),
  47. fUI(nullptr)
  48. {
  49. fCarlaPluginDescriptor = carla_get_native_rack_plugin();
  50. DISTRHO_SAFE_ASSERT_RETURN(fCarlaPluginDescriptor != nullptr,);
  51. memset(&fCarlaHostDescriptor, 0, sizeof(fCarlaHostDescriptor));
  52. memset(&fCarlaTimeInfo, 0, sizeof(fCarlaTimeInfo));
  53. fCarlaHostDescriptor.handle = this;
  54. fCarlaHostDescriptor.resourceDir = "/Users/falktx/Source/Ildaeil"; // carla_get_library_folder();
  55. fCarlaHostDescriptor.uiName = "Ildaeil";
  56. fCarlaHostDescriptor.uiParentId = 0;
  57. fCarlaHostDescriptor.get_buffer_size = host_get_buffer_size;
  58. fCarlaHostDescriptor.get_sample_rate = host_get_sample_rate;
  59. fCarlaHostDescriptor.is_offline = host_is_offline;
  60. fCarlaHostDescriptor.get_time_info = host_get_time_info;
  61. fCarlaHostDescriptor.write_midi_event = host_write_midi_event;
  62. fCarlaHostDescriptor.ui_parameter_changed = nullptr;
  63. fCarlaHostDescriptor.ui_midi_program_changed = nullptr;
  64. fCarlaHostDescriptor.ui_custom_data_changed = nullptr;
  65. fCarlaHostDescriptor.ui_closed = nullptr;
  66. fCarlaHostDescriptor.ui_open_file = nullptr;
  67. fCarlaHostDescriptor.ui_save_file = nullptr;
  68. fCarlaHostDescriptor.dispatcher = host_dispatcher;
  69. fCarlaPluginHandle = fCarlaPluginDescriptor->instantiate(&fCarlaHostDescriptor);
  70. DISTRHO_SAFE_ASSERT_RETURN(fCarlaPluginHandle != nullptr,);
  71. fCarlaHostHandle = carla_create_native_plugin_host_handle(fCarlaPluginDescriptor, fCarlaPluginHandle);
  72. }
  73. ~IldaeilPlugin() override
  74. {
  75. if (fCarlaHostHandle != nullptr)
  76. {
  77. carla_host_handle_free(fCarlaHostHandle);
  78. }
  79. if (fCarlaPluginHandle != nullptr)
  80. fCarlaPluginDescriptor->cleanup(fCarlaPluginHandle);
  81. }
  82. const NativeTimeInfo* hostGetTimeInfo() const noexcept
  83. {
  84. const TimePosition& timePos(getTimePosition());
  85. fCarlaTimeInfo.playing = timePos.playing;
  86. fCarlaTimeInfo.frame = timePos.frame;
  87. fCarlaTimeInfo.bbt.valid = timePos.bbt.valid;
  88. fCarlaTimeInfo.bbt.bar = timePos.bbt.bar;
  89. fCarlaTimeInfo.bbt.beat = timePos.bbt.beat;
  90. fCarlaTimeInfo.bbt.tick = timePos.bbt.tick;
  91. fCarlaTimeInfo.bbt.barStartTick = timePos.bbt.barStartTick;
  92. fCarlaTimeInfo.bbt.beatsPerBar = timePos.bbt.beatsPerBar;
  93. fCarlaTimeInfo.bbt.beatType = timePos.bbt.beatType;
  94. fCarlaTimeInfo.bbt.ticksPerBeat = timePos.bbt.ticksPerBeat;
  95. fCarlaTimeInfo.bbt.beatsPerMinute = timePos.bbt.beatsPerMinute;
  96. return &fCarlaTimeInfo;
  97. }
  98. #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
  99. bool hostWriteMidiEvent(const NativeMidiEvent* const event)
  100. {
  101. MidiEvent midiEvent;
  102. midiEvent.frame = event->time;
  103. midiEvent.size = event->size;
  104. midiEvent.dataExt = nullptr;
  105. uint32_t i = 0;
  106. for (; i < event->size; ++i)
  107. midiEvent.data[i] = event->data[i];
  108. for (; i < MidiEvent::kDataSize; ++i)
  109. midiEvent.data[i] = 0;
  110. return writeMidiEvent(midiEvent);
  111. }
  112. #endif
  113. void hostResizeUI(const uint width, const uint height)
  114. {
  115. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  116. d_stdout("resizing ui to %u %u", width, height);
  117. fUI->setSize(width, height);
  118. }
  119. protected:
  120. /* --------------------------------------------------------------------------------------------------------
  121. * Information */
  122. /**
  123. Get the plugin label.
  124. A plugin label follows the same rules as Parameter::symbol, with the exception that it can start with numbers.
  125. */
  126. const char* getLabel() const override
  127. {
  128. #if DISTRHO_PLUGIN_IS_SYNTH
  129. return "IldaeilSynth";
  130. #elif DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
  131. return "IldaeilMIDI";
  132. #else
  133. return "IldaeilFX";
  134. #endif
  135. }
  136. /**
  137. Get an extensive comment/description about the plugin.
  138. */
  139. const char* getDescription() const override
  140. {
  141. return "Ildaeil is a mini-plugin host working as a plugin, allowing one-to-one plugin format reusage.";
  142. }
  143. /**
  144. Get the plugin author/maker.
  145. */
  146. const char* getMaker() const override
  147. {
  148. return "DISTRHO";
  149. }
  150. /**
  151. Get the plugin homepage.
  152. */
  153. const char* getHomePage() const override
  154. {
  155. return "https://github.com/DISTRHO/Ildaeil";
  156. }
  157. /**
  158. Get the plugin license name (a single line of text).
  159. For commercial plugins this should return some short copyright information.
  160. */
  161. const char* getLicense() const override
  162. {
  163. return "GPLv2+";
  164. }
  165. /**
  166. Get the plugin version, in hexadecimal.
  167. */
  168. uint32_t getVersion() const override
  169. {
  170. return d_version(1, 0, 0);
  171. }
  172. /**
  173. Get the plugin unique Id.
  174. This value is used by LADSPA, DSSI and VST plugin formats.
  175. */
  176. int64_t getUniqueId() const override
  177. {
  178. #if DISTRHO_PLUGIN_IS_SYNTH
  179. return d_cconst('d', 'I', 'l', 'S');
  180. #elif DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
  181. return d_cconst('d', 'I', 'l', 'M');
  182. #else
  183. return d_cconst('d', 'I', 'l', 'F');
  184. #endif
  185. }
  186. /* --------------------------------------------------------------------------------------------------------
  187. * Init */
  188. /* --------------------------------------------------------------------------------------------------------
  189. * Internal data */
  190. /* --------------------------------------------------------------------------------------------------------
  191. * Process */
  192. void activate() override
  193. {
  194. if (fCarlaPluginHandle != nullptr)
  195. fCarlaPluginDescriptor->activate(fCarlaPluginHandle);
  196. }
  197. void deactivate() override
  198. {
  199. if (fCarlaPluginHandle != nullptr)
  200. fCarlaPluginDescriptor->deactivate(fCarlaPluginHandle);
  201. }
  202. void run(const float** inputs, float** outputs, uint32_t frames) override
  203. {
  204. if (fCarlaPluginHandle != nullptr)
  205. {
  206. fCarlaPluginDescriptor->process(fCarlaPluginHandle, (float**)inputs, outputs, frames, nullptr, 0);
  207. }
  208. else
  209. {
  210. std::memset(outputs[0], 0, sizeof(float)*frames);
  211. std::memset(outputs[1], 0, sizeof(float)*frames);
  212. }
  213. }
  214. // -------------------------------------------------------------------------------------------------------
  215. private:
  216. /**
  217. Set our plugin class as non-copyable and add a leak detector just in case.
  218. */
  219. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(IldaeilPlugin)
  220. };
  221. // -----------------------------------------------------------------------------------------------------------
  222. static uint32_t host_get_buffer_size(const NativeHostHandle handle)
  223. {
  224. return static_cast<IldaeilPlugin*>(handle)->getBufferSize();
  225. }
  226. static double host_get_sample_rate(const NativeHostHandle handle)
  227. {
  228. return static_cast<IldaeilPlugin*>(handle)->getSampleRate();
  229. }
  230. static bool host_is_offline(NativeHostHandle)
  231. {
  232. return false;
  233. }
  234. static const NativeTimeInfo* host_get_time_info(const NativeHostHandle handle)
  235. {
  236. return static_cast<IldaeilPlugin*>(handle)->hostGetTimeInfo();
  237. }
  238. static bool host_write_midi_event(const NativeHostHandle handle, const NativeMidiEvent* const event)
  239. {
  240. #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
  241. return static_cast<IldaeilPlugin*>(handle)->hostWriteMidiEvent(event);
  242. #else
  243. return handle != nullptr && event != nullptr && false;
  244. #endif
  245. }
  246. static intptr_t host_dispatcher(const NativeHostHandle handle, const NativeHostDispatcherOpcode opcode,
  247. const int32_t index, const intptr_t value, void* const ptr, const float opt)
  248. {
  249. switch (opcode)
  250. {
  251. case NATIVE_HOST_OPCODE_UI_RESIZE:
  252. static_cast<IldaeilPlugin*>(handle)->hostResizeUI(index, value);
  253. break;
  254. default:
  255. break;
  256. }
  257. return 0;
  258. // unused
  259. (void)ptr;
  260. (void)opt;
  261. }
  262. /* ------------------------------------------------------------------------------------------------------------
  263. * Plugin entry point, called by DPF to create a new plugin instance. */
  264. Plugin* createPlugin()
  265. {
  266. return new IldaeilPlugin();
  267. }
  268. // -----------------------------------------------------------------------------------------------------------
  269. END_NAMESPACE_DISTRHO