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.

372 lines
11KB

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