diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index 9452d2404..cfd8603eb 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -659,6 +659,11 @@ public: */ virtual void sampleRateChanged(const double newSampleRate); + /*! + * Initialize all RT buffers of the plugin. + */ + virtual void initBuffers(); + /*! * TODO. */ @@ -727,6 +732,34 @@ public: */ void postRtEventsRun(); + // ------------------------------------------------------------------- + // Post-poned UI Stuff + + /*! + * Tell the UI a parameter has changed. + */ + virtual void uiParameterChange(const uint32_t index, const float value); + + /*! + * Tell the UI the current program has changed. + */ + virtual void uiProgramChange(const uint32_t index); + + /*! + * Tell the UI the current midi program has changed. + */ + virtual void uiMidiProgramChange(const uint32_t index); + + /*! + * Tell the UI a note has been pressed. + */ + virtual void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo); + + /*! + * Tell the UI a note has been released. + */ + virtual void uiNoteOff(const uint8_t channel, const uint8_t note); + // ------------------------------------------------------------------- // Plugin initializers @@ -768,42 +801,9 @@ protected: friend struct CarlaPluginProtectedData; CarlaPluginProtectedData* const kData; //!< Internal data, for CarlaPlugin subclasses only. - // ------------------------------------------------------------------- - // Post-poned UI Stuff - - /*! - * Tell the UI a parameter has changed. - */ - virtual void uiParameterChange(const uint32_t index, const float value); - - /*! - * Tell the UI the current program has changed. - */ - virtual void uiProgramChange(const uint32_t index); - - /*! - * Tell the UI the current midi program has changed. - */ - virtual void uiMidiProgramChange(const uint32_t index); - - /*! - * Tell the UI a note has been pressed. - */ - virtual void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo); - - /*! - * Tell the UI a note has been released. - */ - virtual void uiNoteOff(const uint8_t channel, const uint8_t note); - // ------------------------------------------------------------------- // Cleanup - /*! - * Initialize all RT buffers of the plugin. - */ - virtual void initBuffers(); - /*! * Delete all temporary buffers of the plugin. */ diff --git a/source/backend/engine/CarlaEngineOsc.cpp b/source/backend/engine/CarlaEngineOsc.cpp index a211df2bf..962d80644 100644 --- a/source/backend/engine/CarlaEngineOsc.cpp +++ b/source/backend/engine/CarlaEngineOsc.cpp @@ -477,7 +477,7 @@ int CarlaEngineOsc::handleMsgControl(CARLA_ENGINE_OSC_HANDLE_ARGS2) const int32_t rindex = argv[0]->i; const float value = argv[1]->f; - plugin->setParameterValueByRIndex(rindex, value, false, true, true); + plugin->setParameterValueByRealIndex(rindex, value, false, true, true); return 0; } diff --git a/source/backend/plugin/CarlaPlugin.pro b/source/backend/plugin/CarlaPlugin.pro index 8164deda0..acc9b312c 100644 --- a/source/backend/plugin/CarlaPlugin.pro +++ b/source/backend/plugin/CarlaPlugin.pro @@ -59,6 +59,7 @@ SOURCES = \ HEADERS = \ CarlaPluginInternal.hpp \ + CarlaPluginGui.hpp \ CarlaPluginThread.hpp HEADERS += \ diff --git a/source/backend/plugin/CarlaPluginGui.cpp b/source/backend/plugin/CarlaPluginGui.cpp index 44c739b22..abb18ad72 100644 --- a/source/backend/plugin/CarlaPluginGui.cpp +++ b/source/backend/plugin/CarlaPluginGui.cpp @@ -15,10 +15,7 @@ * For a full copy of the GNU General Public License see the GPL.txt file */ -#include "CarlaPluginInternal.hpp" - -#include -#include +#include "CarlaPluginGui.hpp" #ifdef Q_WS_X11 # include @@ -26,173 +23,133 @@ CARLA_BACKEND_START_NAMESPACE +#include "moc_CarlaPluginGui.cpp" + // ----------------------------------------------------------------------- // Engine Helpers, defined in CarlaEngine.cpp extern QMainWindow* getEngineHostWindow(CarlaEngine* const engine); -class CarlaPluginGUI : public QMainWindow -{ -public: - class Callback - { - public: - virtual ~Callback() {} - virtual void guiClosedCallback() = 0; - }; - - CarlaPluginGUI(CarlaEngine* const engine, Callback* const callback); - ~CarlaPluginGUI(); - - void idle(); - void resizeLater(int width, int height); - - // Parent UIs - void* getContainerWinId(); - void closeContainer(); - - // Qt4 UIs, TODO - -protected: - void closeEvent(QCloseEvent* const event); - -private: - Callback* const kCallback; - QWidget* fContainer; - - int fNextWidth; - int fNextHeight; - - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginGUI) -}; - // ------------------------------------------------------------------- // CarlaPluginGUI -CarlaPluginGUI::CarlaPluginGUI(CarlaEngine* const engine, Callback* const callback) +CarlaPluginGui::CarlaPluginGui(CarlaEngine* const engine, Callback* const callback, const Options& options) : QMainWindow(getEngineHostWindow(engine)), kCallback(callback), fContainer(nullptr), - fNextWidth(0), - fNextHeight(0) + fOptions(options) { CARLA_ASSERT(callback != nullptr); - carla_debug("CarlaPluginGUI::CarlaPluginGUI(%p, %p)", engine, callback); -} + carla_debug("CarlaPluginGui::CarlaPluginGui(%p, %p)", engine, callback); -CarlaPluginGUI::~CarlaPluginGUI() -{ - carla_debug("CarlaPluginGUI::~CarlaPluginGUI()"); + if (options.parented) + { +#ifdef Q_WS_X11 + fContainer = new QX11EmbedContainer(this); +#else + fContainer = new QWidget(this); +#endif + setCentralWidget(fContainer); + } + +#ifdef Q_OS_WIN + if (! options.resizable) + setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint); +#endif - closeContainer(); + connect(this, SIGNAL(setSizeSafeSignal(int,int)), SLOT(setSizeSafeSlot(int,int))); } -void CarlaPluginGUI::idle() +CarlaPluginGui::~CarlaPluginGui() { - if (fNextWidth > 0 && fNextHeight > 0) + carla_debug("CarlaPluginGui::~CarlaPluginGui()"); + + if (fOptions.parented) { - setFixedSize(fNextWidth, fNextHeight); - fNextWidth = 0; - fNextHeight = 0; + CARLA_ASSERT(fContainer != nullptr); +#ifdef Q_WS_X11 + delete (QX11EmbedContainer*)fContainer; +#else + delete fContainer; +#endif + } + else + { + CARLA_ASSERT(fContainer == nullptr); } } -void CarlaPluginGUI::resizeLater(int width, int height) +void CarlaPluginGui::setSize(const int width, const int height) { CARLA_ASSERT_INT(width > 0, width); CARLA_ASSERT_INT(height > 0, height); + carla_debug("CarlaPluginGui::setSize(%i, %i)", width, height); if (width <= 0) return; if (height <= 0) return; - fNextWidth = width; - fNextHeight = height; + emit setSizeSafeSignal(width, height); } -void* CarlaPluginGUI::getContainerWinId() +void* CarlaPluginGui::getContainerWinId() { - carla_debug("CarlaPluginGUI::getContainerWinId()"); - - if (fContainer == nullptr) - { -#ifdef Q_WS_X11 - QX11EmbedContainer* container(new QX11EmbedContainer(this)); -#else - QWidget* container(new QWidget(this)); -#endif - setCentralWidget(container); - fContainer = container; - } + CARLA_ASSERT(fContainer != nullptr); + carla_debug("CarlaPluginGui::getContainerWinId()"); - return (void*)fContainer->winId(); + return (fContainer != nullptr) ? (void*)fContainer->winId() : nullptr; } -void CarlaPluginGUI::closeContainer() +void CarlaPluginGui::setWidget(QWidget* const widget) { - carla_debug("CarlaPluginGUI::closeContainer()"); + CARLA_ASSERT(fContainer == nullptr); + carla_debug("CarlaPluginGui::setWidget(%p)", widget); - if (fContainer != nullptr) - { -#ifdef Q_WS_X11 - delete (QX11EmbedContainer*)fContainer; -#else - delete (QWidget*)fContainer; -#endif - fContainer = nullptr; - } + setCentralWidget(widget); + widget->setParent(this); + + fContainer = widget; } -void CarlaPluginGUI::closeEvent(QCloseEvent* const event) +void CarlaPluginGui::removeWidget() { - carla_debug("CarlaPluginGUI::closeEvent(%p)", event); - CARLA_ASSERT(event != nullptr); - - if (event == nullptr) - return; + CARLA_ASSERT(fContainer != nullptr); + carla_debug("CarlaPluginGui::removeWidget()"); - if (! event->spontaneous()) - { - event->ignore(); + if (fContainer == nullptr) return; - } - if (kCallback != nullptr) - kCallback->guiClosedCallback(); + fContainer->setParent(nullptr); + setCentralWidget(nullptr); - QMainWindow::closeEvent(event); + fContainer = nullptr; } -// ------------------------------------------------------------------- -// CarlaPluginGUI - -#if 0 -void createUiIfNeeded(CarlaPluginGUI::Callback* const callback) +void CarlaPluginGui::closeEvent(QCloseEvent* const event) { - if (gui != nullptr) - return; - - gui = new CarlaPluginGUI(engine, callback); -} + CARLA_ASSERT(event != nullptr); + carla_debug("CarlaPluginGui::closeEvent(%p)", event); -void destroyUiIfNeeded() -{ - if (gui == nullptr) + if (event == nullptr) return; - gui->close(); - delete gui; - gui = nullptr; + if (event->spontaneous() && kCallback != nullptr) + kCallback->guiClosedCallback(); + + QMainWindow::closeEvent(event); } -void resizeUiLater(int width, int height) +void CarlaPluginGui::setSizeSafeSlot(int width, int height) { - if (gui == nullptr) - return; + carla_debug("CarlaPluginGui::setSizeSafeSlot(%i, %i)", width, height); - gui->resizeLater(width, height); + if (fOptions.resizable) + resize(width, height); + else + setFixedSize(width, height); } -#endif + +// ------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE diff --git a/source/backend/plugin/CarlaPluginGui.hpp b/source/backend/plugin/CarlaPluginGui.hpp new file mode 100644 index 000000000..b316156ab --- /dev/null +++ b/source/backend/plugin/CarlaPluginGui.hpp @@ -0,0 +1,78 @@ +/* + * Carla Plugin + * Copyright (C) 2011-2013 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 GPL.txt file + */ + +#ifndef __CARLA_PLUGIN_GUI_HPP__ +#define __CARLA_PLUGIN_GUI_HPP__ + +#include "CarlaPluginInternal.hpp" + +#include +#include + +CARLA_BACKEND_START_NAMESPACE + +class CarlaPluginGui : public QMainWindow +{ + Q_OBJECT + +public: + class Callback + { + public: + virtual ~Callback() {} + virtual void guiClosedCallback() = 0; + }; + + struct Options { + bool parented; + bool resizable; + }; + + CarlaPluginGui(CarlaEngine* const engine, Callback* const callback, const Options& options); + ~CarlaPluginGui(); + + void setSize(const int width, const int height); + + // Parent UIs + void* getContainerWinId(); + + // Qt UIs + void setWidget(QWidget* widget); + void removeWidget(); + +protected: + void closeEvent(QCloseEvent* const event); + +private: + Callback* const kCallback; + QWidget* fContainer; + const Options fOptions; + +signals: + void setSizeSafeSignal(int, int); + +private slots: + void setSizeSafeSlot(int width, int height); + +#ifndef MOC_PARSING + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginGui) +#endif +}; + +CARLA_BACKEND_END_NAMESPACE + +#endif // __CARLA_PLUGIN_GUI_HPP__ diff --git a/source/backend/plugin/CarlaPluginInternal.hpp b/source/backend/plugin/CarlaPluginInternal.hpp index 8f0a70a9c..c0b199097 100644 --- a/source/backend/plugin/CarlaPluginInternal.hpp +++ b/source/backend/plugin/CarlaPluginInternal.hpp @@ -377,24 +377,12 @@ struct ExternalMidiNote { class CarlaPluginGui; -class CarlaPluginGuiCallback -{ -public: - virtual ~CarlaPluginGuiCallback() {} - -protected: - virtual void guiClosedCallback() = 0; -}; - -// ----------------------------------------------------------------------- - struct CarlaPluginProtectedData { CarlaEngine* const engine; CarlaEngineClient* client; CarlaPluginGui* gui; bool active; - //bool activeBefore; bool needsReset; void* lib; @@ -524,7 +512,6 @@ struct CarlaPluginProtectedData { client(nullptr), gui(nullptr), active(false), - //activeBefore(false), needsReset(false), lib(nullptr), ctrlChannel(0), @@ -576,11 +563,6 @@ struct CarlaPluginProtectedData { } } - // defined in CarlaPluginGui.cpp - void createUiIfNeeded(CarlaPluginGuiCallback* const callback); - void destroyUiIfNeeded(); - void resizeUiLater(int width, int height); - static CarlaEngine* getEngine(CarlaPlugin* const plugin) { return plugin->kData->engine; diff --git a/source/backend/plugin/Makefile b/source/backend/plugin/Makefile index 7c546eff6..18f9a088b 100644 --- a/source/backend/plugin/Makefile +++ b/source/backend/plugin/Makefile @@ -27,6 +27,7 @@ endif OBJS = \ CarlaPlugin.cpp.o \ + CarlaPluginGui.cpp.o \ CarlaPluginThread.cpp.o \ BridgePlugin.cpp.o \ NativePlugin.cpp.o \ @@ -53,9 +54,12 @@ debug: # -------------------------------------------------------------- -%.cpp.o: %.cpp ../CarlaBackend.hpp ../CarlaEngine.hpp ../CarlaPlugin.hpp CarlaPluginInternal.hpp CarlaPluginThread.hpp +%.cpp.o: %.cpp ../CarlaBackend.hpp ../CarlaEngine.hpp ../CarlaPlugin.hpp CarlaPluginGui.hpp CarlaPluginInternal.hpp CarlaPluginThread.hpp moc_CarlaPluginGui.cpp $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ +moc_%.cpp: %.hpp + $(MOC) $< -DMOC_PARSING -o $@ + $(SHARED): $(OBJS) $(CXX) $^ -shared $(LINK_FLAGS) -o $@ diff --git a/source/backend/plugin/VstPlugin.cpp b/source/backend/plugin/VstPlugin.cpp index 0c00b89c0..853956d55 100644 --- a/source/backend/plugin/VstPlugin.cpp +++ b/source/backend/plugin/VstPlugin.cpp @@ -19,6 +19,7 @@ #ifdef WANT_VST +#include "CarlaPluginGui.hpp" #include "CarlaVstUtils.hpp" //#ifdef Q_WS_X11 @@ -38,7 +39,7 @@ const unsigned int PLUGIN_WANTS_MIDI_INPUT = 0x8000; //!< VST Plugin wants /**@}*/ class VstPlugin : public CarlaPlugin, - public CarlaPluginGuiCallback + public CarlaPluginGui::Callback { public: VstPlugin(CarlaEngine* const engine, const unsigned short id) @@ -360,14 +361,20 @@ public: { if (yesNo) { - kData->createUiIfNeeded(this); + if (kData->gui == nullptr) + { + struct CarlaPluginGui::Options guiOptions; + guiOptions.parented = true; + guiOptions.resizable = false; + + kData->gui = new CarlaPluginGui(kData->engine, this, guiOptions); + } int32_t value = 0; #ifdef Q_WS_X11 //value = (intptr_t)QX11Info::display(); #endif - // TODO!! - void* const ptr = nullptr; //kData->gui->getContainerWinId(); + void* const ptr = kData->gui->getContainerWinId(); if (dispatcher(effEditOpen, 0, value, ptr, 0.0f) != 0) { @@ -380,18 +387,22 @@ public: const int16_t width = vstRect->right - vstRect->left; const int16_t height = vstRect->bottom - vstRect->top; - //if (width > 0 && height > 0) - //{ - // kData->gui->setFixedSize(width, height); - //} + if (width > 0 && height > 0) + kData->gui->setSize(width, height); } - //kData->gui->setWindowTitle(QString("%1 (GUI)").arg((const char*)fName).toUtf8().constData()); - //kData->gui->show(); + kData->gui->setWindowTitle(QString("%1 (GUI)").arg((const char*)fName).toUtf8().constData()); + kData->gui->show(); } else { - kData->destroyUiIfNeeded(); + if (kData->gui != nullptr) + { + kData->gui->close(); + delete kData->gui; + kData->gui = nullptr; + } + kData->engine->callback(CALLBACK_ERROR, fId, 0, 0, 0.0f, "Plugin refused to open its own UI"); kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr); return; @@ -400,7 +411,13 @@ public: else { dispatcher(effEditClose, 0, 0, nullptr, 0.0f); - kData->destroyUiIfNeeded(); + + if (kData->gui != nullptr) + { + kData->gui->close(); + delete kData->gui; + kData->gui = nullptr; + } } } @@ -1873,8 +1890,11 @@ protected: break; case audioMasterSizeWindow: - kData->resizeUiLater(index, value); - ret = 1; + if (kData->gui != nullptr) + { + kData->gui->setSize(index, value); + ret = 1; + } break; case audioMasterGetSampleRate: