diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 183a8eb14..5bb8a7ee4 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -21,8 +21,7 @@ #include #include - -//#include +#include CARLA_BACKEND_START_NAMESPACE @@ -1972,24 +1971,16 @@ CarlaPlugin::ScopedProcessLocker::~ScopedProcessLocker() // ------------------------------------------------------------------- // CarlaPluginGUI -#if 0 CarlaPluginGUI::CarlaPluginGUI(QWidget* const parent, Callback* const callback) : QMainWindow(parent), - kCallback(callback) + kCallback(callback), + fContainer(this) { - carla_debug("CarlaPluginGUI::CarlaPluginGUI(%p)", parent); - //CARLA_ASSERT(callback); - - //m_container = new GuiContainer(this); - //setCentralWidget(m_container); - //adjustSize(); - - //m_container->setParent(this); - //m_container->show(); - - //m_resizable = true; + carla_debug("CarlaPluginGUI::CarlaPluginGUI(%p, %p)", parent, callback); + CARLA_ASSERT(callback != nullptr); - //setNewSize(50, 50); + setCentralWidget(&fContainer); + adjustSize(); QMainWindow::setVisible(false); } @@ -1997,109 +1988,30 @@ CarlaPluginGUI::CarlaPluginGUI(QWidget* const parent, Callback* const callback) CarlaPluginGUI::~CarlaPluginGUI() { carla_debug("CarlaPluginGUI::~CarlaPluginGUI()"); - //CARLA_ASSERT(m_container); - - // FIXME, automatically deleted by parent ? - //delete m_container; -} -#endif - -#if 0 - -// ------------------------------------------------------------------- - -GuiContainer* CarlaPluginGUI::getContainer() const -{ - return m_container; } WId CarlaPluginGUI::getWinId() const { - return m_container->winId(); -} - -// ------------------------------------------------------------------- - -void CarlaPluginGUI::setNewSize(int width, int height) -{ - carla_debug("CarlaPluginGUI::setNewSize(%i, %i)", width, height); - - if (width < 30) - width = 30; - if (height < 30) - height = 30; - - if (m_resizable) - { - resize(width, height); - } - else - { - setFixedSize(width, height); - m_container->setFixedSize(width, height); - } -} - -void CarlaPluginGUI::setResizable(bool resizable) -{ - m_resizable = resizable; - setNewSize(width(), height()); - -#ifdef Q_OS_WIN - if (! resizable) - setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint); -#endif -} - -void CarlaPluginGUI::setTitle(const char* const title) -{ - CARLA_ASSERT(title); - setWindowTitle(QString("%1 (GUI)").arg(title)); -} - -void CarlaPluginGUI::setVisible(const bool yesNo) -{ - carla_debug("CarlaPluginGUI::setVisible(%s)", bool2str(yesNo)); - - if (yesNo) - { - if (! m_geometry.isNull()) - restoreGeometry(m_geometry); - } - else - m_geometry = saveGeometry(); - - QMainWindow::setVisible(yesNo); -} - -// ------------------------------------------------------------------- - -void CarlaPluginGUI::hideEvent(QHideEvent* const event) -{ - carla_debug("CarlaPluginGUI::hideEvent(%p)", event); - CARLA_ASSERT(event); - - event->accept(); - close(); + carla_debug("CarlaPluginGUI::getWinId()"); + return fContainer.winId(); } void CarlaPluginGUI::closeEvent(QCloseEvent* const event) { carla_debug("CarlaPluginGUI::closeEvent(%p)", event); - CARLA_ASSERT(event); + CARLA_ASSERT(event != nullptr); - if (event->spontaneous()) + if (! event->spontaneous()) { - if (m_callback) - m_callback->guiClosedCallback(); - - QMainWindow::closeEvent(event); + event->ignore(); return; } - event->ignore(); + if (kCallback != nullptr) + kCallback->guiClosedCallback(); + + QMainWindow::closeEvent(event); } -#endif // ------------------------------------------------------------------- diff --git a/source/backend/plugin/CarlaPluginInternal.hpp b/source/backend/plugin/CarlaPluginInternal.hpp index 16476c17c..bcd5db8c9 100644 --- a/source/backend/plugin/CarlaPluginInternal.hpp +++ b/source/backend/plugin/CarlaPluginInternal.hpp @@ -31,6 +31,14 @@ #include +#ifdef Q_WS_X11 +# include +typedef QX11EmbedContainer GuiContainer; +#else +# include +typedef QWidget GuiContainer; +#endif + #define CARLA_DECLARE_NON_COPY_STRUCT(structName) \ structName(structName&) = delete; \ structName(const structName&) = delete; @@ -400,8 +408,14 @@ public: CarlaPluginGUI(QWidget* const parent, Callback* const callback); ~CarlaPluginGUI(); + WId getWinId() const; + +protected: + void closeEvent(QCloseEvent* const event); + private: Callback* const kCallback; + GuiContainer fContainer; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginGUI) }; @@ -559,6 +573,24 @@ struct CarlaPluginProtectedData { CarlaPluginProtectedData(CarlaPluginProtectedData&) = delete; CarlaPluginProtectedData(const CarlaPluginProtectedData&) = delete; + void createUiIfNeeded(CarlaPluginGUI::Callback* const callback) + { + if (gui != nullptr) + return; + + gui = new CarlaPluginGUI(nullptr, callback); + } + + void destroyUiIfNeeded() + { + if (gui == nullptr) + return; + + gui->close(); + delete gui; + gui = nullptr; + } + static CarlaEngine* getEngine(CarlaPlugin* const plugin) { return plugin->kData->engine; @@ -587,104 +619,3 @@ struct CarlaPluginProtectedData { CARLA_BACKEND_END_NAMESPACE #endif // __CARLA_PLUGIN_INTERNAL_HPP__ - -// common includes -//#include -//#include -//#include -//#include - -//#ifdef Q_WS_X11 -//# include -//typedef QX11EmbedContainer GuiContainer; -//#else -//# include -//typedef QWidget GuiContainer; -//#endif - -#if 0 - -/*! - * \class CarlaPluginGUI - * - * \brief Carla Backend gui plugin class - * - * \see CarlaPlugin - */ -class CarlaPluginGUI : public QMainWindow -{ -public: - /*! - * \class Callback - * - * \brief Carla plugin GUI callback - */ - class Callback - { - public: - virtual ~Callback() {} - virtual void guiClosedCallback() = 0; - }; - - // ------------------------------------------------------------------- - // Constructor and destructor - - /*! - * TODO - */ - CarlaPluginGUI(QWidget* const parent, Callback* const callback); - - /*! - * TODO - */ - ~CarlaPluginGUI(); - - // ------------------------------------------------------------------- - // Get data - - /*! - * TODO - */ - GuiContainer* getContainer() const; - - /*! - * TODO - */ - WId getWinId() const; - - // ------------------------------------------------------------------- - // Set data - - /*! - * TODO - */ - void setNewSize(const int width, const int height); - - /*! - * TODO - */ - void setResizable(const bool resizable); - - /*! - * TODO - */ - void setTitle(const char* const title); - - /*! - * TODO - */ - void setVisible(const bool yesNo); - - // ------------------------------------------------------------------- - -private: - Callback* const m_callback; - GuiContainer* m_container; - - QByteArray m_geometry; - bool m_resizable; - - void hideEvent(QHideEvent* const event); - void closeEvent(QCloseEvent* const event); -}; -#endif diff --git a/source/backend/plugin/VstPlugin.cpp b/source/backend/plugin/VstPlugin.cpp index c22580080..9aaed4b01 100644 --- a/source/backend/plugin/VstPlugin.cpp +++ b/source/backend/plugin/VstPlugin.cpp @@ -37,7 +37,8 @@ const unsigned int PLUGIN_USES_OLD_VSTSDK = 0x4000; //!< VST Plugin uses a const unsigned int PLUGIN_WANTS_MIDI_INPUT = 0x8000; //!< VST Plugin wants MIDI input /**@}*/ -class VstPlugin : public CarlaPlugin +class VstPlugin : public CarlaPlugin, + public CarlaPluginGUI::Callback { public: VstPlugin(CarlaEngine* const engine, const unsigned short id) @@ -332,39 +333,9 @@ public: void setGuiContainer(GuiContainer* const container) { - carla_debug("VstPlugin::setGuiContainer(%p)", container); - CARLA_ASSERT(container); - - if (gui.type == GUI_EXTERNAL_OSC) - return; - - int32_t value = 0; - void* const ptr = (void*)container->winId(); - ERect* vstRect = nullptr; - -#ifdef Q_WS_X11 - value = (intptr_t)QX11Info::display(); -#endif - - // get UI size before opening UI, plugin may refuse this - effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0.0f); - - if (vstRect) - { - int width = vstRect->right - vstRect->left; - int height = vstRect->bottom - vstRect->top; - - if (width > 0 || height > 0) - { - container->setFixedSize(width, height); -#ifdef BUILD_BRIDGE - x_engine->callback(CALLBACK_RESIZE_GUI, m_id, width, height, 1.0, nullptr); -#endif - } - } // open UI - if (effect->dispatcher(effect, effEditOpen, 0, value, ptr, 0.0f) == 1) + { // get UI size again, can't fail now vstRect = nullptr; @@ -398,7 +369,7 @@ public: m_hints &= ~PLUGIN_HAS_GUI; x_engine->callback(CALLBACK_SHOW_GUI, m_id, -1, 0, 0.0, nullptr); - effect->dispatcher(effect, effEditClose, 0, 0, nullptr, 0.0f); + } } #endif @@ -426,8 +397,49 @@ public: } else { - if (yesNo && fGui.width > 0 && fGui.height > 0 && kData->gui != nullptr) - kData->gui->setFixedSize(fGui.width, fGui.height); + if (yesNo) + { + kData->createUiIfNeeded(this); + + int32_t value = 0; +#ifdef Q_WS_X11 + //value = (intptr_t)QX11Info::display(); +#endif + void* const ptr = (void*)kData->gui->getWinId(); + + if (dispatcher(effEditOpen, 0, value, ptr, 0.0f) == 1) + { + ERect* vstRect = nullptr; + + dispatcher(effEditGetRect, 0, 0, &vstRect, 0.0f); + + if (vstRect != nullptr) + { + 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); + } + } + + kData->gui->setWindowTitle(QString("%1 (GUI)").arg((const char*)fName)); + kData->gui->show(); + } + else + { + kData->destroyUiIfNeeded(); + 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; + } + } + else if (fGui.isVisible) + { + dispatcher(effEditClose, 0, 0, nullptr, 0.0f); + kData->destroyUiIfNeeded(); + } } fGui.isVisible = yesNo; @@ -1601,9 +1613,18 @@ public: // ------------------------------------------------------------------- protected: + void guiClosedCallback() + { + showGui(false); + kData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr); + } + intptr_t dispatcher(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) { - carla_debug("VstPlugin::dispatcher(%02i:%s, %i, " P_INTPTR ", %p, %f)", opcode, vstEffectOpcode2str(opcode), index, value, ptr, opt); +#if defined(DEBUG) && ! defined(CARLA_OS_WIN) + if (opcode != effEditIdle && opcode != effProcessEvents) + carla_debug("VstPlugin::dispatcher(%02i:%s, %i, " P_INTPTR ", %p, %f)", opcode, vstEffectOpcode2str(opcode), index, value, ptr, opt); +#endif CARLA_ASSERT(fEffect != nullptr); return (fEffect != nullptr) ? fEffect->dispatcher(fEffect, opcode, index, value, ptr, opt) : 0; @@ -1649,21 +1670,38 @@ protected: switch (opcode) { case audioMasterAutomate: - CARLA_ASSERT(fEnabled); CARLA_ASSERT_INT(index < static_cast(kData->param.count), index); + CARLA_SAFE_ASSERT(fEnabled); // plugins should never do this! if (index < 0 || index >= static_cast(kData->param.count) || ! fEnabled) break; - if (fIsProcessing && ! kData->engine->isOffline()) + if (fIsProcessing) { + // Called from engine + if (kData->engine->isOffline()) + { + setParameterValue(index, opt, true, true, true); + } + else + { + setParameterValue(index, opt, false, false, false); + postponeRtEvent(kPluginPostRtEventParameterChange, index, 0, opt); + } + } + else if (! kData->active) + { + // On init? setParameterValue(index, opt, false, false, false); - postponeRtEvent(kPluginPostRtEventParameterChange, index, 0, opt); + } + else if (fGui.isVisible) + { + // Called from GUI + setParameterValue(index, opt, false, true, true); } else { - CARLA_ASSERT(fGui.isVisible); // FIXME - remove when offline is implemented - setParameterValue(index, opt, fIsProcessing, true, true); + carla_stdout("audioMasterAutomate called from unknown source"); } break; @@ -1802,8 +1840,7 @@ protected: break; case audioMasterSizeWindow: - fGui.width = index; - fGui.height = value; + CARLA_ASSERT(kData->gui != nullptr); // FIXME - ensure thread safe if (kData->gui != nullptr) @@ -2125,14 +2162,10 @@ private: struct GuiInfo { bool isOsc; bool isVisible; - int width; - int height; GuiInfo() : isOsc(false), - isVisible(false), - width(0), - height(0) {} + isVisible(false) {} } fGui; bool fIsProcessing; diff --git a/source/carla.py b/source/carla.py index 684ad993a..7125147e7 100755 --- a/source/carla.py +++ b/source/carla.py @@ -1541,7 +1541,7 @@ def engineCallback(ptr, action, pluginId, value1, value2, value3, valueStr): #elif action == CALLBACK_NSM_SAVE: #Carla.gui.emit(SIGNAL("NSM_SaveCallback()")) elif action == CALLBACK_ERROR: - Carla.gui.emit(SIGNAL("ErrorCallback(QString)"), valueStr) + Carla.gui.emit(SIGNAL("ErrorCallback(QString)"), cString(valueStr)) elif action == CALLBACK_QUIT: Carla.gui.emit(SIGNAL("QuitCallback()")) diff --git a/source/utils/CarlaVstUtils.hpp b/source/utils/CarlaVstUtils.hpp index 29f0c1e11..80bcd6b93 100644 --- a/source/utils/CarlaVstUtils.hpp +++ b/source/utils/CarlaVstUtils.hpp @@ -182,6 +182,10 @@ const char* vstEffectOpcode2str(const int32_t opcode) return "effEditMouse"; case effEditKey: return "effEditKey"; +#endif + case effEditIdle: + return "effEditIdle"; +#if ! VST_FORCE_DEPRECATED case effEditTop: return "effEditTop"; case effEditSleep: