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.

282 lines
9.0KB

  1. /*
  2. * DISTRHO Cardinal Plugin
  3. * Copyright (C) 2021-2022 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 <audio.hpp>
  19. #include <context.hpp>
  20. #include <midi.hpp>
  21. #ifdef NDEBUG
  22. # undef DEBUG
  23. #endif
  24. #include "CardinalRemote.hpp"
  25. #include "DistrhoPlugin.hpp"
  26. #if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
  27. # include "WindowParameters.hpp"
  28. #else
  29. # define kWindowParameterCount 0
  30. #endif
  31. #ifndef HEADLESS
  32. # include "DistrhoUI.hpp"
  33. #else
  34. # include "Base.hpp"
  35. START_NAMESPACE_DGL
  36. class TopLevelWidget;
  37. template <class BaseWidget> class NanoBaseWidget;
  38. typedef NanoBaseWidget<TopLevelWidget> NanoTopLevelWidget;
  39. END_NAMESPACE_DGL
  40. #endif
  41. START_NAMESPACE_DISTRHO
  42. // -----------------------------------------------------------------------------------------------------------
  43. static constexpr const uint kModuleParameterCount = 24;
  44. enum CardinalVariant {
  45. kCardinalVariantMain,
  46. kCardinalVariantMini,
  47. kCardinalVariantFX,
  48. kCardinalVariantNative,
  49. kCardinalVariantSynth,
  50. };
  51. enum CardinalParameters {
  52. kCardinalParameterCountAtModules = kModuleParameterCount,
  53. kCardinalParameterBypass = kCardinalParameterCountAtModules,
  54. #if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
  55. kCardinalParameterStartWindow,
  56. kCardinalParameterCountAtWindow = kCardinalParameterStartWindow + kWindowParameterCount,
  57. #if CARDINAL_VARIANT_MINI
  58. kCardinalParameterStartMini = kCardinalParameterCountAtWindow,
  59. kCardinalParameterStartMiniBuffers = kCardinalParameterStartMini,
  60. kCardinalParameterMiniAudioIn1 = kCardinalParameterStartMiniBuffers,
  61. kCardinalParameterMiniAudioIn2,
  62. kCardinalParameterMiniCVIn1,
  63. kCardinalParameterMiniCVIn2,
  64. kCardinalParameterMiniCVIn3,
  65. kCardinalParameterMiniCVIn4,
  66. kCardinalParameterMiniCVIn5,
  67. kCardinalParameterCountAtMiniBuffers,
  68. kCardinalParameterStartMiniTime = kCardinalParameterCountAtMiniBuffers,
  69. kCardinalParameterMiniTimeFlags = kCardinalParameterStartMiniTime,
  70. kCardinalParameterMiniTimeBar,
  71. kCardinalParameterMiniTimeBeat,
  72. kCardinalParameterMiniTimeBeatsPerBar,
  73. kCardinalParameterMiniTimeBeatType,
  74. kCardinalParameterMiniTimeFrame,
  75. kCardinalParameterMiniTimeBarStartTick,
  76. kCardinalParameterMiniTimeBeatsPerMinute,
  77. kCardinalParameterMiniTimeTick,
  78. kCardinalParameterMiniTimeTicksPerBeat,
  79. kCardinalParameterCountAtMiniTime,
  80. kCardinalParameterCountAtMini = kCardinalParameterCountAtMiniTime,
  81. kCardinalParameterCount = kCardinalParameterCountAtMini
  82. #else
  83. kCardinalParameterCount = kCardinalParameterCountAtWindow
  84. #endif
  85. #else
  86. kCardinalParameterCount
  87. #endif
  88. };
  89. enum CardinalStates {
  90. kCardinalStatePatch,
  91. kCardinalStateScreenshot,
  92. kCardinalStateComment,
  93. #if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
  94. kCardinalStateWindowSize,
  95. #endif
  96. #if CARDINAL_VARIANT_MINI
  97. kCardinalStateParamChange,
  98. #endif
  99. kCardinalStateCount
  100. };
  101. static_assert(kCardinalParameterBypass == kModuleParameterCount, "valid parameter indexes");
  102. #if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
  103. static_assert(kCardinalParameterStartWindow == kModuleParameterCount + 1, "valid parameter indexes");
  104. static_assert(kCardinalParameterStartWindow == kCardinalParameterBypass + 1, "valid parameter indexes");
  105. static_assert(kCardinalParameterCountAtWindow == kModuleParameterCount + kWindowParameterCount + 1, "valid parameter indexes");
  106. #endif
  107. #if CARDINAL_VARIANT_MINI
  108. static_assert(0 == kCardinalParameterStartMini - kCardinalParameterMiniAudioIn1, "valid parameter indexes");
  109. static_assert(kCardinalParameterStartMini == kCardinalParameterCountAtWindow, "valid parameter indexes");
  110. static_assert(kCardinalParameterStartMini == kCardinalParameterBypass + kWindowParameterCount + 1, "valid parameter indexes");
  111. static_assert(kCardinalParameterStartMini == kModuleParameterCount + kWindowParameterCount + 1, "valid parameter indexes");
  112. static_assert(kCardinalParameterCountAtWindow == kModuleParameterCount + kWindowParameterCount + 1, "valid parameter indexes");
  113. static_assert(DISTRHO_PLUGIN_NUM_INPUTS == kCardinalParameterCountAtMiniBuffers - kCardinalParameterStartMiniBuffers, "valid parameter indexes");
  114. #endif
  115. class UI;
  116. // -----------------------------------------------------------------------------------------------------------
  117. struct CardinalPluginContext : rack::Context {
  118. uint32_t bufferSize, processCounter;
  119. double sampleRate;
  120. float parameters[kModuleParameterCount];
  121. CardinalVariant variant;
  122. bool bypassed, playing, reset, bbtValid;
  123. int32_t bar, beat, beatsPerBar, beatType;
  124. uint64_t frame;
  125. double barStartTick, beatsPerMinute;
  126. double tick, tickClock, ticksPerBeat, ticksPerClock, ticksPerFrame;
  127. uintptr_t nativeWindowId;
  128. const float* const* dataIns;
  129. float** dataOuts;
  130. const MidiEvent* midiEvents;
  131. uint32_t midiEventCount;
  132. Plugin* const plugin;
  133. NanoTopLevelWidget* tlw;
  134. UI* ui;
  135. CardinalPluginContext(Plugin* const p)
  136. : bufferSize(p != nullptr ? p->getBufferSize() : 0),
  137. processCounter(0),
  138. sampleRate(p != nullptr ? p->getSampleRate() : 0.0),
  139. #if CARDINAL_VARIANT_MAIN
  140. variant(kCardinalVariantMain),
  141. #elif CARDINAL_VARIANT_MINI
  142. variant(kCardinalVariantMini),
  143. #elif CARDINAL_VARIANT_FX
  144. variant(kCardinalVariantFX),
  145. #elif CARDINAL_VARIANT_NATIVE
  146. variant(kCardinalVariantNative),
  147. #elif CARDINAL_VARIANT_SYNTH
  148. variant(kCardinalVariantSynth),
  149. #else
  150. #error cardinal variant not set
  151. #endif
  152. bypassed(false),
  153. playing(false),
  154. reset(false),
  155. bbtValid(false),
  156. bar(1),
  157. beat(1),
  158. beatsPerBar(4),
  159. beatType(4),
  160. frame(0),
  161. barStartTick(0.0),
  162. beatsPerMinute(120.0),
  163. tick(0.0),
  164. tickClock(0.0),
  165. ticksPerBeat(0.0),
  166. ticksPerClock(0.0),
  167. ticksPerFrame(0.0),
  168. nativeWindowId(0),
  169. dataIns(nullptr),
  170. dataOuts(nullptr),
  171. midiEvents(nullptr),
  172. midiEventCount(0),
  173. plugin(p),
  174. tlw(nullptr),
  175. ui(nullptr)
  176. {
  177. std::memset(parameters, 0, sizeof(parameters));
  178. }
  179. void writeMidiMessage(const rack::midi::Message& message, uint8_t channel);
  180. #ifndef HEADLESS
  181. bool addIdleCallback(IdleCallback* cb) const;
  182. void removeIdleCallback(IdleCallback* cb) const;
  183. #endif
  184. };
  185. // -----------------------------------------------------------------------------------------------------------
  186. #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  187. CardinalPluginContext* getRackContextFromPlugin(void* ptr);
  188. #endif
  189. class CardinalBasePlugin : public Plugin {
  190. public:
  191. CardinalPluginContext* const context;
  192. CardinalBasePlugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount)
  193. : Plugin(parameterCount, programCount, stateCount),
  194. context(new CardinalPluginContext(this)) {}
  195. ~CardinalBasePlugin() override {}
  196. #ifdef HAVE_LIBLO
  197. virtual bool startRemoteServer(const char* port) = 0;
  198. virtual void stopRemoteServer() = 0;
  199. virtual void stepRemoteServer() = 0;
  200. #endif
  201. #ifndef HEADLESS
  202. friend class CardinalUI;
  203. #endif
  204. };
  205. #ifndef HEADLESS
  206. struct WasmRemotePatchLoadingDialog;
  207. class CardinalBaseUI : public UI {
  208. public:
  209. CardinalPluginContext* const context;
  210. remoteUtils::RemoteDetails* remoteDetails;
  211. bool saving;
  212. bool savingUncompressed;
  213. #ifdef DISTRHO_OS_WASM
  214. WasmRemotePatchLoadingDialog* psDialog;
  215. #endif
  216. // for 3rd party modules
  217. std::function<void(char* path)> filebrowseraction;
  218. FileBrowserHandle filebrowserhandle;
  219. CardinalBaseUI(const uint width, const uint height)
  220. : UI(width, height),
  221. #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  222. context(getRackContextFromPlugin(getPluginInstancePointer())),
  223. #else
  224. context(new CardinalPluginContext(nullptr)),
  225. #endif
  226. remoteDetails(nullptr),
  227. saving(false),
  228. savingUncompressed(false),
  229. #ifdef DISTRHO_OS_WASM
  230. psDialog(nullptr),
  231. #endif
  232. filebrowseraction(),
  233. filebrowserhandle(nullptr)
  234. {
  235. context->tlw = this;
  236. context->ui = this;
  237. }
  238. ~CardinalBaseUI() override
  239. {
  240. remoteUtils::disconnectFromRemote(remoteDetails);
  241. if (filebrowserhandle != nullptr)
  242. fileBrowserClose(filebrowserhandle);
  243. }
  244. };
  245. #endif
  246. // -----------------------------------------------------------------------------------------------------------
  247. END_NAMESPACE_DISTRHO