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.

332 lines
11KB

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