Audio plugin host https://kx.studio/carla
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.

187 lines
5.2KB

  1. /*
  2. * Carla Native Plugin UI launcher
  3. * Copyright (C) 2018-2023 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 doc/GPL.txt file.
  16. */
  17. #include "dgl/OpenGL.hpp"
  18. #include "dgl/src/pugl.hpp"
  19. #include "dgl/src/WindowPrivateData.hpp"
  20. #include "CarlaNative.h"
  21. #include "ui_launcher_res.hpp"
  22. #include "CarlaDefines.h"
  23. // --------------------------------------------------------------------------------------------------------------------
  24. START_NAMESPACE_DISTRHO
  25. class PluginApplication : public DGL_NAMESPACE::Application
  26. {
  27. public:
  28. explicit PluginApplication()
  29. : Application(false)
  30. {
  31. setClassName("CarlaPluginWrapper");
  32. }
  33. };
  34. class PluginWindow : public DGL_NAMESPACE::Window
  35. {
  36. public:
  37. explicit PluginWindow(PluginApplication& app, const uintptr_t winId)
  38. : Window(app,
  39. winId,
  40. ui_launcher_res::carla_uiWidth,
  41. ui_launcher_res::carla_uiHeight,
  42. 0.0,
  43. false,
  44. false,
  45. false,
  46. false)
  47. {
  48. // this is called just before creating UI, ensuring proper context to it
  49. if (pData->view != nullptr && pData->initPost())
  50. puglBackendEnter(pData->view);
  51. }
  52. ~PluginWindow()
  53. {
  54. if (pData->view != nullptr)
  55. puglBackendLeave(pData->view);
  56. }
  57. // called right before deleting UI, ensuring correct context
  58. void enterContextForDeletion()
  59. {
  60. if (pData->view != nullptr)
  61. puglBackendEnter(pData->view);
  62. }
  63. // called after creating UI, restoring proper context
  64. void leaveContextAfterCreation()
  65. {
  66. if (pData->view != nullptr)
  67. puglBackendLeave(pData->view);
  68. }
  69. };
  70. END_NAMESPACE_DISTRHO
  71. // --------------------------------------------------------------------------------------------------------------------
  72. START_NAMESPACE_DGL
  73. class CarlaButtonWidget : public TopLevelWidget,
  74. private OpenGLImageButton::Callback
  75. {
  76. public:
  77. explicit CarlaButtonWidget(PluginWindow& parent, const NativePluginDescriptor* const d, const NativePluginHandle h)
  78. : TopLevelWidget(parent),
  79. startButtonImage(ui_launcher_res::carla_uiData,
  80. ui_launcher_res::carla_uiWidth,
  81. ui_launcher_res::carla_uiHeight,
  82. kImageFormatBGR),
  83. startButton(this, startButtonImage),
  84. descriptor(d),
  85. handle(h),
  86. pluginWindow(parent)
  87. {
  88. const uint width = ui_launcher_res::carla_uiWidth;
  89. const uint height = ui_launcher_res::carla_uiHeight;
  90. Widget::setSize(width, height);
  91. setGeometryConstraints(width, height, true, true, true);
  92. startButton.setCallback(this);
  93. pluginWindow.leaveContextAfterCreation();
  94. }
  95. ~CarlaButtonWidget() override
  96. {
  97. pluginWindow.enterContextForDeletion();
  98. }
  99. protected:
  100. void onDisplay() override
  101. {
  102. }
  103. void imageButtonClicked(OpenGLImageButton* imageButton, int) override
  104. {
  105. if (imageButton != &startButton)
  106. return;
  107. if (descriptor->ui_show != nullptr)
  108. descriptor->ui_show(handle, true);
  109. }
  110. private:
  111. OpenGLImage startButtonImage;
  112. OpenGLImageButton startButton;
  113. const NativePluginDescriptor* const descriptor;
  114. const NativePluginHandle handle;
  115. PluginWindow& pluginWindow;
  116. CARLA_DECLARE_NON_COPYABLE(CarlaButtonWidget);
  117. };
  118. END_NAMESPACE_DGL
  119. // --------------------------------------------------------------------------------------------------------------------
  120. USE_NAMESPACE_DGL
  121. struct CarlaUILauncher {
  122. PluginApplication app;
  123. PluginWindow window;
  124. CarlaButtonWidget widget;
  125. CarlaUILauncher(const uintptr_t winId, const NativePluginDescriptor* const d, const NativePluginHandle h)
  126. : app(),
  127. window(app, winId),
  128. widget(window, d, h) {}
  129. };
  130. CarlaUILauncher* createUILauncher(const uintptr_t winId,
  131. const NativePluginDescriptor* const d,
  132. const NativePluginHandle h)
  133. {
  134. return new CarlaUILauncher(winId, d, h);
  135. }
  136. void getUILauncherSize(CarlaUILauncher* const ui, VstRect* const rect)
  137. {
  138. rect->right = ui->window.getWidth();
  139. rect->bottom = ui->window.getHeight();
  140. #ifdef DISTRHO_OS_MAC
  141. const double scaleFactor = ui->window.getScaleFactor();
  142. rect->right /= scaleFactor;
  143. rect->bottom /= scaleFactor;
  144. #endif
  145. }
  146. void idleUILauncher(CarlaUILauncher* const ui)
  147. {
  148. ui->app.idle();
  149. }
  150. void destoryUILauncher(CarlaUILauncher* const ui)
  151. {
  152. delete ui;
  153. }
  154. // --------------------------------------------------------------------------------------------------------------------