| @@ -21,8 +21,7 @@ | |||
| #include <QtCore/QFile> | |||
| #include <QtCore/QTextStream> | |||
| //#include <QtGui/QtEvents> | |||
| #include <QtGui/QCloseEvent> | |||
| 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 | |||
| // ------------------------------------------------------------------- | |||
| @@ -31,6 +31,14 @@ | |||
| #include <QtGui/QMainWindow> | |||
| #ifdef Q_WS_X11 | |||
| # include <QtGui/QX11EmbedContainer> | |||
| typedef QX11EmbedContainer GuiContainer; | |||
| #else | |||
| # include <QtGui/QWidget> | |||
| 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 <cmath> | |||
| //#include <vector> | |||
| //#include <QtCore/QMutex> | |||
| //#include <QtGui/QMainWindow> | |||
| //#ifdef Q_WS_X11 | |||
| //# include <QtGui/QX11EmbedContainer> | |||
| //typedef QX11EmbedContainer GuiContainer; | |||
| //#else | |||
| //# include <QtGui/QWidget> | |||
| //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 | |||
| @@ -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<int32_t>(kData->param.count), index); | |||
| CARLA_SAFE_ASSERT(fEnabled); // plugins should never do this! | |||
| if (index < 0 || index >= static_cast<int32_t>(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; | |||
| @@ -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()")) | |||
| @@ -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: | |||