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.

179 lines
5.0KB

  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, winId, ui_launcher_res::carla_uiWidth, ui_launcher_res::carla_uiHeight, 0.0, false, false, false)
  39. {
  40. // this is called just before creating UI, ensuring proper context to it
  41. if (pData->view != nullptr && pData->initPost())
  42. puglBackendEnter(pData->view);
  43. }
  44. ~PluginWindow()
  45. {
  46. if (pData->view != nullptr)
  47. puglBackendLeave(pData->view);
  48. }
  49. // called right before deleting UI, ensuring correct context
  50. void enterContextForDeletion()
  51. {
  52. if (pData->view != nullptr)
  53. puglBackendEnter(pData->view);
  54. }
  55. // called after creating UI, restoring proper context
  56. void leaveContextAfterCreation()
  57. {
  58. if (pData->view != nullptr)
  59. puglBackendLeave(pData->view);
  60. }
  61. };
  62. END_NAMESPACE_DISTRHO
  63. // --------------------------------------------------------------------------------------------------------------------
  64. START_NAMESPACE_DGL
  65. class CarlaButtonWidget : public TopLevelWidget,
  66. private OpenGLImageButton::Callback
  67. {
  68. public:
  69. explicit CarlaButtonWidget(PluginWindow& parent, const NativePluginDescriptor* const d, const NativePluginHandle h)
  70. : TopLevelWidget(parent),
  71. startButtonImage(ui_launcher_res::carla_uiData,
  72. ui_launcher_res::carla_uiWidth,
  73. ui_launcher_res::carla_uiHeight,
  74. kImageFormatBGR),
  75. startButton(this, startButtonImage),
  76. descriptor(d),
  77. handle(h),
  78. pluginWindow(parent)
  79. {
  80. const uint width = ui_launcher_res::carla_uiWidth;
  81. const uint height = ui_launcher_res::carla_uiHeight;
  82. Widget::setSize(width, height);
  83. setGeometryConstraints(width, height, true, true, true);
  84. startButton.setCallback(this);
  85. pluginWindow.leaveContextAfterCreation();
  86. }
  87. ~CarlaButtonWidget() override
  88. {
  89. pluginWindow.enterContextForDeletion();
  90. }
  91. protected:
  92. void onDisplay() override
  93. {
  94. }
  95. void imageButtonClicked(OpenGLImageButton* imageButton, int) override
  96. {
  97. if (imageButton != &startButton)
  98. return;
  99. if (descriptor->ui_show != nullptr)
  100. descriptor->ui_show(handle, true);
  101. }
  102. private:
  103. OpenGLImage startButtonImage;
  104. OpenGLImageButton startButton;
  105. const NativePluginDescriptor* const descriptor;
  106. const NativePluginHandle handle;
  107. PluginWindow& pluginWindow;
  108. CARLA_DECLARE_NON_COPYABLE(CarlaButtonWidget);
  109. };
  110. END_NAMESPACE_DGL
  111. // --------------------------------------------------------------------------------------------------------------------
  112. USE_NAMESPACE_DGL
  113. struct CarlaUILauncher {
  114. PluginApplication app;
  115. PluginWindow window;
  116. CarlaButtonWidget widget;
  117. CarlaUILauncher(const uintptr_t winId, const NativePluginDescriptor* const d, const NativePluginHandle h)
  118. : app(),
  119. window(app, winId),
  120. widget(window, d, h) {}
  121. };
  122. CarlaUILauncher* createUILauncher(const uintptr_t winId,
  123. const NativePluginDescriptor* const d,
  124. const NativePluginHandle h)
  125. {
  126. return new CarlaUILauncher(winId, d, h);
  127. }
  128. void getUILauncherSize(CarlaUILauncher* const ui, VstRect* const rect)
  129. {
  130. rect->right = ui->window.getWidth();
  131. rect->bottom = ui->window.getHeight();
  132. #ifdef DISTRHO_OS_MAC
  133. const double scaleFactor = ui->window.getScaleFactor();
  134. rect->right /= scaleFactor;
  135. rect->bottom /= scaleFactor;
  136. #endif
  137. }
  138. void idleUILauncher(CarlaUILauncher* const ui)
  139. {
  140. ui->app.idle();
  141. }
  142. void destoryUILauncher(CarlaUILauncher* const ui)
  143. {
  144. delete ui;
  145. }
  146. // --------------------------------------------------------------------------------------------------------------------