/* * Carla Native Plugin UI launcher * Copyright (C) 2018-2023 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "dgl/OpenGL.hpp" #include "dgl/src/pugl.hpp" #include "dgl/src/WindowPrivateData.hpp" #include "CarlaNative.h" #include "ui_launcher_res.hpp" #include "CarlaDefines.h" // -------------------------------------------------------------------------------------------------------------------- START_NAMESPACE_DISTRHO class PluginApplication : public DGL_NAMESPACE::Application { public: explicit PluginApplication() : Application(false) { setClassName("CarlaPluginWrapper"); } }; class PluginWindow : public DGL_NAMESPACE::Window { public: explicit PluginWindow(PluginApplication& app, const uintptr_t winId) : Window(app, winId, ui_launcher_res::carla_uiWidth, ui_launcher_res::carla_uiHeight, 0.0, false, false, false) { // this is called just before creating UI, ensuring proper context to it if (pData->view != nullptr && pData->initPost()) puglBackendEnter(pData->view); } ~PluginWindow() { if (pData->view != nullptr) puglBackendLeave(pData->view); } // called right before deleting UI, ensuring correct context void enterContextForDeletion() { if (pData->view != nullptr) puglBackendEnter(pData->view); } // called after creating UI, restoring proper context void leaveContextAfterCreation() { if (pData->view != nullptr) puglBackendLeave(pData->view); } }; END_NAMESPACE_DISTRHO // -------------------------------------------------------------------------------------------------------------------- START_NAMESPACE_DGL class CarlaButtonWidget : public TopLevelWidget, private OpenGLImageButton::Callback { public: explicit CarlaButtonWidget(PluginWindow& parent, const NativePluginDescriptor* const d, const NativePluginHandle h) : TopLevelWidget(parent), startButtonImage(ui_launcher_res::carla_uiData, ui_launcher_res::carla_uiWidth, ui_launcher_res::carla_uiHeight, kImageFormatBGR), startButton(this, startButtonImage), descriptor(d), handle(h), pluginWindow(parent) { const uint width = ui_launcher_res::carla_uiWidth; const uint height = ui_launcher_res::carla_uiHeight; Widget::setSize(width, height); setGeometryConstraints(width, height, true, true, true); startButton.setCallback(this); pluginWindow.leaveContextAfterCreation(); } ~CarlaButtonWidget() override { pluginWindow.enterContextForDeletion(); } protected: void onDisplay() override { } void imageButtonClicked(OpenGLImageButton* imageButton, int) override { if (imageButton != &startButton) return; if (descriptor->ui_show != nullptr) descriptor->ui_show(handle, true); } private: OpenGLImage startButtonImage; OpenGLImageButton startButton; const NativePluginDescriptor* const descriptor; const NativePluginHandle handle; PluginWindow& pluginWindow; CARLA_DECLARE_NON_COPYABLE(CarlaButtonWidget); }; END_NAMESPACE_DGL // -------------------------------------------------------------------------------------------------------------------- USE_NAMESPACE_DGL struct CarlaUILauncher { PluginApplication app; PluginWindow window; CarlaButtonWidget widget; CarlaUILauncher(const uintptr_t winId, const NativePluginDescriptor* const d, const NativePluginHandle h) : app(), window(app, winId), widget(window, d, h) {} }; CarlaUILauncher* createUILauncher(const uintptr_t winId, const NativePluginDescriptor* const d, const NativePluginHandle h) { return new CarlaUILauncher(winId, d, h); } void getUILauncherSize(CarlaUILauncher* const ui, VstRect* const rect) { rect->right = ui->window.getWidth(); rect->bottom = ui->window.getHeight(); } void idleUILauncher(CarlaUILauncher* const ui) { ui->app.idle(); } void destoryUILauncher(CarlaUILauncher* const ui) { delete ui; } // --------------------------------------------------------------------------------------------------------------------