| @@ -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. | |||
| */ | |||
| @@ -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; | |||
| } | |||
| @@ -59,6 +59,7 @@ SOURCES = \ | |||
| HEADERS = \ | |||
| CarlaPluginInternal.hpp \ | |||
| CarlaPluginGui.hpp \ | |||
| CarlaPluginThread.hpp | |||
| HEADERS += \ | |||
| @@ -15,10 +15,7 @@ | |||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||
| */ | |||
| #include "CarlaPluginInternal.hpp" | |||
| #include <QtGui/QMainWindow> | |||
| #include <QtGui/QCloseEvent> | |||
| #include "CarlaPluginGui.hpp" | |||
| #ifdef Q_WS_X11 | |||
| # include <QtGui/QX11EmbedContainer> | |||
| @@ -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 | |||
| @@ -0,0 +1,78 @@ | |||
| /* | |||
| * Carla Plugin | |||
| * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * 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 <QtGui/QMainWindow> | |||
| #include <QtGui/QCloseEvent> | |||
| 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__ | |||
| @@ -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; | |||
| @@ -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 $@ | |||
| @@ -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: | |||