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.

353 lines
10KB

  1. /*
  2. * DISTRHO Cardinal 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 3 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. #pragma once
  18. #include "PluginContext.hpp"
  19. START_NAMESPACE_DISTRHO
  20. // -----------------------------------------------------------------------------------------------------------
  21. struct CardinalAudioDevice : rack::audio::Device
  22. {
  23. CardinalBasePlugin* const fPlugin;
  24. CardinalAudioDevice(CardinalBasePlugin* const plugin)
  25. : fPlugin(plugin) {}
  26. std::string getName() override
  27. {
  28. return "Cardinal";
  29. }
  30. int getNumInputs() override
  31. {
  32. return DISTRHO_PLUGIN_NUM_INPUTS;
  33. }
  34. int getNumOutputs() override
  35. {
  36. return DISTRHO_PLUGIN_NUM_OUTPUTS;
  37. }
  38. int getBlockSize() override
  39. {
  40. return fPlugin->getBufferSize();
  41. }
  42. float getSampleRate() override
  43. {
  44. return fPlugin->getSampleRate();
  45. }
  46. std::set<int> getBlockSizes() override
  47. {
  48. return std::set<int>({ getBlockSize() });
  49. }
  50. std::set<float> getSampleRates() override
  51. {
  52. return std::set<float>({ getSampleRate() });
  53. }
  54. void setBlockSize(int) override {}
  55. void setSampleRate(float) override {}
  56. };
  57. // -----------------------------------------------------------------------------------------------------------
  58. struct CardinalAudioDriver : rack::audio::Driver
  59. {
  60. CardinalAudioDriver() {}
  61. std::string getName() override
  62. {
  63. return "Plugin Driver";
  64. }
  65. std::vector<int> getDeviceIds() override
  66. {
  67. return std::vector<int>({ 0 });
  68. }
  69. int getDefaultDeviceId() override
  70. {
  71. return 0;
  72. }
  73. std::string getDeviceName(int) override
  74. {
  75. return "Plugin Device";
  76. }
  77. int getDeviceNumInputs(int) override
  78. {
  79. return DISTRHO_PLUGIN_NUM_INPUTS;
  80. }
  81. int getDeviceNumOutputs(int) override
  82. {
  83. return DISTRHO_PLUGIN_NUM_OUTPUTS;
  84. }
  85. rack::audio::Device* subscribe(int, rack::audio::Port* const port) override
  86. {
  87. CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(port->context);
  88. DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr, nullptr);
  89. CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
  90. DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr);
  91. if (! plugin->canAssignAudioDevice())
  92. throw rack::Exception("Plugin driver only allows one audio device to be used simultaneously");
  93. CardinalAudioDevice* const device = new CardinalAudioDevice(plugin);
  94. device->subscribe(port);
  95. if (plugin->isActive())
  96. device->onStartStream();
  97. plugin->assignAudioDevice(device);
  98. return device;
  99. }
  100. void unsubscribe(int, rack::audio::Port* const port) override
  101. {
  102. CardinalAudioDevice* const device = reinterpret_cast<CardinalAudioDevice*>(port->device);
  103. DISTRHO_SAFE_ASSERT_RETURN(device != nullptr,);
  104. CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(port->context);
  105. DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr,);
  106. CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
  107. DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,);
  108. if (plugin->clearAudioDevice(device))
  109. {
  110. device->onStopStream();
  111. device->unsubscribe(port);
  112. delete device;
  113. }
  114. }
  115. };
  116. // -----------------------------------------------------------------------------------------------------------
  117. struct CardinalMidiInputDevice : rack::midi::InputDevice
  118. {
  119. CardinalBasePlugin* const fPlugin;
  120. rack::midi::Message msg;
  121. CardinalMidiInputDevice(CardinalBasePlugin* const plugin)
  122. : fPlugin(plugin)
  123. {
  124. msg.bytes.reserve(0xff);
  125. }
  126. std::string getName() override
  127. {
  128. return "Cardinal";
  129. }
  130. void handleMessagesFromHost(const MidiEvent* const midiEvents, const uint32_t midiEventCount)
  131. {
  132. if (subscribed.size() == 0)
  133. return;
  134. for (uint32_t i=0; i<midiEventCount; ++i)
  135. {
  136. const MidiEvent& midiEvent(midiEvents[i]);
  137. const uint8_t* data;
  138. if (midiEvent.size > MidiEvent::kDataSize)
  139. {
  140. data = midiEvent.dataExt;
  141. msg.bytes.reserve(midiEvent.size);
  142. }
  143. else
  144. {
  145. data = midiEvent.data;
  146. }
  147. msg.frame = midiEvent.frame;
  148. std::memcpy(msg.bytes.data(), data, midiEvent.size);
  149. onMessage(msg);
  150. }
  151. }
  152. };
  153. // -----------------------------------------------------------------------------------------------------------
  154. struct CardinalMidiOutputDevice : rack::midi::OutputDevice
  155. {
  156. CardinalBasePlugin* const fPlugin;
  157. MidiEvent fQueue[128];
  158. Mutex fQueueMutex;
  159. uint8_t fQueueIndex;
  160. CardinalMidiOutputDevice(CardinalBasePlugin* const plugin)
  161. : fPlugin(plugin),
  162. fQueueIndex(0) {}
  163. std::string getName() override
  164. {
  165. return "Cardinal";
  166. }
  167. void processMessages()
  168. {
  169. const MutexLocker cml(fQueueMutex);
  170. for (uint8_t i=0; i<fQueueIndex; ++i)
  171. fPlugin->writeMidiEvent(fQueue[i]);
  172. fQueueIndex = 0;
  173. }
  174. void sendMessage(const rack::midi::Message& message) override
  175. {
  176. if (message.bytes.size() < 3) // FIXME
  177. return;
  178. if ((message.bytes[0] & 0xf0) == 0xf0)
  179. return;
  180. if (fQueueIndex == 128)
  181. return;
  182. const MutexLocker cml(fQueueMutex);
  183. MidiEvent& event(fQueue[fQueueIndex++]);
  184. event.frame = message.frame < 0 ? 0 : (message.frame - fPlugin->context->engine->getBlockFrame());
  185. event.size = 3; // FIXME
  186. std::memcpy(event.data, message.bytes.data(), event.size);
  187. }
  188. };
  189. // -----------------------------------------------------------------------------------------------------------
  190. struct CardinalMidiDriver : rack::midi::Driver
  191. {
  192. CardinalMidiDriver() {}
  193. std::string getName() override
  194. {
  195. return "Plugin Driver";
  196. }
  197. std::vector<int> getInputDeviceIds() override
  198. {
  199. return std::vector<int>({ 0 });
  200. }
  201. std::vector<int> getOutputDeviceIds() override
  202. {
  203. return std::vector<int>({ 0 });
  204. }
  205. int getDefaultInputDeviceId() override
  206. {
  207. return 0;
  208. }
  209. int getDefaultOutputDeviceId() override
  210. {
  211. return 0;
  212. }
  213. std::string getInputDeviceName(int) override
  214. {
  215. return "Plugin Device";
  216. }
  217. std::string getOutputDeviceName(int) override
  218. {
  219. return "Plugin Device";
  220. }
  221. rack::midi::InputDevice* subscribeInput(int, rack::midi::Input* const input) override
  222. {
  223. CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(input->context);
  224. DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr, nullptr);
  225. CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
  226. DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr);
  227. CardinalMidiInputDevice* const device = new CardinalMidiInputDevice(plugin);
  228. device->subscribe(input);
  229. plugin->addMidiInput(device);
  230. return device;
  231. }
  232. rack::midi::OutputDevice* subscribeOutput(int, rack::midi::Output* const output) override
  233. {
  234. CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(output->context);
  235. DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr, nullptr);
  236. CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
  237. DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr);
  238. if (! plugin->canAssignMidiOutputDevice())
  239. throw rack::Exception("Plugin driver only allows one midi output device to be used simultaneously");
  240. CardinalMidiOutputDevice* const device = new CardinalMidiOutputDevice(plugin);
  241. device->subscribe(output);
  242. plugin->assignMidiOutputDevice(device);
  243. return device;
  244. }
  245. void unsubscribeInput(int, rack::midi::Input* const input) override
  246. {
  247. CardinalMidiInputDevice* const device = reinterpret_cast<CardinalMidiInputDevice*>(input->device);
  248. DISTRHO_SAFE_ASSERT_RETURN(device != nullptr,);
  249. CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(input->context);
  250. DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr,);
  251. CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
  252. DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,);
  253. plugin->removeMidiInput(device);
  254. device->unsubscribe(input);
  255. delete device;
  256. }
  257. void unsubscribeOutput(int, rack::midi::Output* const output) override
  258. {
  259. CardinalMidiOutputDevice* const device = reinterpret_cast<CardinalMidiOutputDevice*>(output->device);
  260. DISTRHO_SAFE_ASSERT_RETURN(device != nullptr,);
  261. CardinalPluginContext* const pluginContext = reinterpret_cast<CardinalPluginContext*>(output->context);
  262. DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr,);
  263. CardinalBasePlugin* const plugin = reinterpret_cast<CardinalBasePlugin*>(pluginContext->plugin);
  264. DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,);
  265. if (plugin->clearMidiOutputDevice(device))
  266. {
  267. device->unsubscribe(output);
  268. delete device;
  269. }
  270. }
  271. };
  272. // -----------------------------------------------------------------------------------------------------------
  273. END_NAMESPACE_DISTRHO