| @@ -1066,23 +1066,16 @@ void set_chunk_data(unsigned short plugin_id, const char* chunk_data) | |||||
| qCritical("CarlaBackendStandalone::set_chunk_data(%i, \"%s\") - could not find plugin", plugin_id, chunk_data); | qCritical("CarlaBackendStandalone::set_chunk_data(%i, \"%s\") - could not find plugin", plugin_id, chunk_data); | ||||
| } | } | ||||
| void set_gui_data(unsigned short plugin_id, uintptr_t gui_addr) | |||||
| void set_gui_container(unsigned short plugin_id, uintptr_t gui_addr) | |||||
| { | { | ||||
| qDebug("CarlaBackendStandalone::set_gui_data(%i, " P_UINTPTR ")", plugin_id, gui_addr); | |||||
| qDebug("CarlaBackendStandalone::set_gui_container(%i, " P_UINTPTR ")", plugin_id, gui_addr); | |||||
| CarlaBackend::CarlaPlugin* const plugin = carlaEngine->getPlugin(plugin_id); | CarlaBackend::CarlaPlugin* const plugin = carlaEngine->getPlugin(plugin_id); | ||||
| if (plugin) | if (plugin) | ||||
| { | |||||
| #ifdef __WINE__ | |||||
| plugin->setGuiData((HWND)gui_addr); | |||||
| #else | |||||
| plugin->setGuiData((QDialog*)CarlaBackend::getPointer(gui_addr)); | |||||
| #endif | |||||
| return; | |||||
| } | |||||
| return plugin->setGuiContainer((GuiContainer*)CarlaBackend::getPointer(gui_addr)); | |||||
| qCritical("CarlaBackendStandalone::set_gui_data(%i, " P_UINTPTR ") - could not find plugin", plugin_id, gui_addr); | |||||
| qCritical("CarlaBackendStandalone::set_gui_container(%i, " P_UINTPTR ") - could not find plugin", plugin_id, gui_addr); | |||||
| } | } | ||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -152,7 +152,7 @@ CARLA_EXPORT void set_midi_program(unsigned short plugin_id, uint32_t midi_progr | |||||
| CARLA_EXPORT void set_custom_data(unsigned short plugin_id, CarlaBackend::CustomDataType dtype, const char* key, const char* value); | CARLA_EXPORT void set_custom_data(unsigned short plugin_id, CarlaBackend::CustomDataType dtype, const char* key, const char* value); | ||||
| CARLA_EXPORT void set_chunk_data(unsigned short plugin_id, const char* chunk_data); | CARLA_EXPORT void set_chunk_data(unsigned short plugin_id, const char* chunk_data); | ||||
| CARLA_EXPORT void set_gui_data(unsigned short plugin_id, uintptr_t gui_addr); | |||||
| CARLA_EXPORT void set_gui_container(unsigned short plugin_id, uintptr_t gui_addr); | |||||
| CARLA_EXPORT void show_gui(unsigned short plugin_id, bool yesno); | CARLA_EXPORT void show_gui(unsigned short plugin_id, bool yesno); | ||||
| CARLA_EXPORT void idle_guis(); | CARLA_EXPORT void idle_guis(); | ||||
| @@ -497,8 +497,8 @@ public: | |||||
| Q_ASSERT(index >= 0 && index < (int32_t)param.count); | Q_ASSERT(index >= 0 && index < (int32_t)param.count); | ||||
| Q_ASSERT(min < max); | Q_ASSERT(min < max); | ||||
| Q_ASSERT(def > min); | |||||
| Q_ASSERT(def < max); | |||||
| Q_ASSERT(def >= min); | |||||
| Q_ASSERT(def <= max); | |||||
| if (index >= 0 && index < (int32_t)param.count) | if (index >= 0 && index < (int32_t)param.count) | ||||
| { | { | ||||
| @@ -28,8 +28,8 @@ CarlaEngine::CarlaEngine() | |||||
| : m_checkThread(this), | : m_checkThread(this), | ||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| m_osc(this), | m_osc(this), | ||||
| m_oscData(nullptr), | |||||
| #endif | #endif | ||||
| m_oscData(nullptr), | |||||
| m_callback(nullptr), | m_callback(nullptr), | ||||
| #ifdef Q_COMPILER_INITIALIZER_LISTS | #ifdef Q_COMPILER_INITIALIZER_LISTS | ||||
| m_callbackPtr(nullptr), | m_callbackPtr(nullptr), | ||||
| @@ -529,12 +529,16 @@ void CarlaEngine::midiUnlock() | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // OSC Stuff | // OSC Stuff | ||||
| #ifndef BUILD_BRIDGE | |||||
| bool CarlaEngine::isOscControllerRegisted() const | bool CarlaEngine::isOscControllerRegisted() const | ||||
| { | { | ||||
| #ifndef BUILD_BRIDGE | |||||
| return m_osc.isControllerRegistered(); | return m_osc.isControllerRegistered(); | ||||
| #else | |||||
| return bool(m_oscData); | |||||
| #endif | |||||
| } | } | ||||
| #ifndef BUILD_BRIDGE | |||||
| const char* CarlaEngine::getOscServerPath() const | const char* CarlaEngine::getOscServerPath() const | ||||
| { | { | ||||
| return m_osc.getServerPath(); | return m_osc.getServerPath(); | ||||
| @@ -260,8 +260,9 @@ public: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // OSC Stuff | // OSC Stuff | ||||
| #ifndef BUILD_BRIDGE | |||||
| bool isOscControllerRegisted() const; | bool isOscControllerRegisted() const; | ||||
| #ifndef BUILD_BRIDGE | |||||
| const char* getOscServerPath() const; | const char* getOscServerPath() const; | ||||
| #else | #else | ||||
| void setOscBridgeData(const CarlaOscData* const oscData); | void setOscBridgeData(const CarlaOscData* const oscData); | ||||
| @@ -35,6 +35,13 @@ | |||||
| #include <vector> | #include <vector> | ||||
| #include <QtGui/QDialog> | #include <QtGui/QDialog> | ||||
| #ifdef Q_WS_X11 | |||||
| #include <QtGui/QX11EmbedContainer> | |||||
| typedef QX11EmbedContainer GuiContainer; | |||||
| #else | |||||
| typedef QWidget GuiContainer; | |||||
| #endif | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| /*! | /*! | ||||
| @@ -1255,14 +1262,13 @@ public: | |||||
| // Set gui stuff | // Set gui stuff | ||||
| /*! | /*! | ||||
| * Set the plugin's custom GUI data.\n | |||||
| * Parameters change between plugin types. | |||||
| * Set the plugin's custom GUI container.\n | |||||
| * | * | ||||
| * \note This function must be always called from the main thread. | * \note This function must be always called from the main thread. | ||||
| */ | */ | ||||
| virtual void setGuiData(QDialog* const dialog) | |||||
| virtual void setGuiContainer(GuiContainer* const container) | |||||
| { | { | ||||
| Q_UNUSED(dialog); | |||||
| Q_UNUSED(container); | |||||
| } | } | ||||
| /*! | /*! | ||||
| @@ -1393,10 +1399,10 @@ public: | |||||
| */ | */ | ||||
| void registerToOsc() | void registerToOsc() | ||||
| { | { | ||||
| #ifndef BUILD_BRIDGE | |||||
| if (! x_engine->isOscControllerRegisted()) | if (! x_engine->isOscControllerRegisted()) | ||||
| return; | return; | ||||
| #ifndef BUILD_BRIDGE | |||||
| x_engine->osc_send_control_add_plugin(m_id, m_name); | x_engine->osc_send_control_add_plugin(m_id, m_name); | ||||
| #endif | #endif | ||||
| @@ -73,12 +73,7 @@ void CarlaCheckThread::run() | |||||
| while (engine->isRunning() && ! m_stopNow) | while (engine->isRunning() && ! m_stopNow) | ||||
| { | { | ||||
| const ScopedLocker m(this); | const ScopedLocker m(this); | ||||
| #ifdef BUILD_BRIDGE | |||||
| oscControllerRegisted = true; | |||||
| #else | |||||
| oscControllerRegisted = engine->isOscControllerRegisted(); | oscControllerRegisted = engine->isOscControllerRegisted(); | ||||
| #endif | |||||
| for (unsigned short i=0; i < maxPluginNumber; i++) | for (unsigned short i=0; i < maxPluginNumber; i++) | ||||
| { | { | ||||
| @@ -887,8 +887,11 @@ public: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Set gui stuff | // Set gui stuff | ||||
| void setGuiData(QDialog* const dialog) | |||||
| void setGuiContainer(GuiContainer* const container) | |||||
| { | { | ||||
| qDebug("Lv2Plugin::setGuiContainer(%p)", container); | |||||
| Q_ASSERT(container); | |||||
| switch(gui.type) | switch(gui.type) | ||||
| { | { | ||||
| case GUI_NONE: | case GUI_NONE: | ||||
| @@ -898,9 +901,11 @@ public: | |||||
| if (ui.widget) | if (ui.widget) | ||||
| { | { | ||||
| QWidget* const widget = (QWidget*)ui.widget; | QWidget* const widget = (QWidget*)ui.widget; | ||||
| dialog->layout()->addWidget(widget); | |||||
| Q_ASSERT(container->layout()); | |||||
| Q_ASSERT(widget); | |||||
| container->layout()->addWidget(widget); | |||||
| widget->adjustSize(); | widget->adjustSize(); | ||||
| widget->setParent(dialog); | |||||
| widget->setParent(container); | |||||
| widget->show(); | widget->show(); | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -910,10 +915,8 @@ public: | |||||
| case GUI_INTERNAL_X11: | case GUI_INTERNAL_X11: | ||||
| if (ui.descriptor) | if (ui.descriptor) | ||||
| { | { | ||||
| features[lv2_feature_id_ui_parent]->data = (void*)dialog->winId(); | |||||
| ui.handle = ui.descriptor->instantiate(ui.descriptor, | |||||
| descriptor->URI, ui.rdf_descriptor->Bundle, | |||||
| carla_lv2_ui_write_function, this, &ui.widget,features); | |||||
| features[lv2_feature_id_ui_parent]->data = (void*)container->winId(); | |||||
| ui.handle = ui.descriptor->instantiate(ui.descriptor, descriptor->URI, ui.rdf_descriptor->Bundle, carla_lv2_ui_write_function, this, &ui.widget, features); | |||||
| updateUi(); | updateUi(); | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -328,19 +328,22 @@ public: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Set gui stuff | // Set gui stuff | ||||
| void setGuiData(QDialog* const dialog) | |||||
| void setGuiContainer(GuiContainer* const container) | |||||
| { | { | ||||
| Q_ASSERT(dialog); | |||||
| qDebug("VstPlugin::setGuiContainer(%p)", container); | |||||
| Q_ASSERT(container); | |||||
| if (gui.type == GUI_EXTERNAL_OSC) | if (gui.type == GUI_EXTERNAL_OSC) | ||||
| return; | return; | ||||
| int32_t value = 0; | |||||
| int32_t value = 0; | |||||
| void* const ptr = (void*)container->winId(); | |||||
| #ifdef Q_WS_X11 | #ifdef Q_WS_X11 | ||||
| value = (int64_t)QX11Info::display(); | |||||
| value = (intptr_t)QX11Info::display(); | |||||
| #endif | #endif | ||||
| if (effect->dispatcher(effect, effEditOpen, 0, value, (void*)dialog->winId(), 0.0f) == 1) | |||||
| if (effect->dispatcher(effect, effEditOpen, 0, value, ptr, 0.0f) == 1) | |||||
| { | { | ||||
| ERect* vstRect = nullptr; | ERect* vstRect = nullptr; | ||||
| effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0.0f); | effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0.0f); | ||||
| @@ -352,19 +355,24 @@ public: | |||||
| if (width <= 0 || height <= 0) | if (width <= 0 || height <= 0) | ||||
| { | { | ||||
| qCritical("VstPlugin::setGuiData(%p) - failed to get proper window size", dialog); | |||||
| qCritical("VstPlugin::setGuiContainer(%p) - failed to get proper window size", container); | |||||
| return; | return; | ||||
| } | } | ||||
| gui.width = width; | gui.width = width; | ||||
| gui.height = height; | gui.height = height; | ||||
| container->setFixedSize(width, height); | |||||
| qDebug("VstPlugin::setGuiContainer(%p) -> setFixedSize(%i, %i)", container, width, height); | |||||
| } | } | ||||
| else | else | ||||
| qCritical("VstPlugin::setGuiData(%p) - failed to get plugin window size", dialog); | |||||
| qCritical("VstPlugin::setGuiContainer(%p) - failed to get plugin window size", container); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| // failed to open UI | // failed to open UI | ||||
| qWarning("VstPlugin::setGuiContainer(%p) - failed to open UI", container); | |||||
| m_hints &= ~PLUGIN_HAS_GUI; | m_hints &= ~PLUGIN_HAS_GUI; | ||||
| x_engine->callback(CALLBACK_SHOW_GUI, m_id, -1, 0, 0.0); | x_engine->callback(CALLBACK_SHOW_GUI, m_id, -1, 0, 0.0); | ||||
| @@ -2008,11 +2016,9 @@ public: | |||||
| break; | break; | ||||
| case audioMasterUpdateDisplay: | case audioMasterUpdateDisplay: | ||||
| Q_ASSERT(self && effect); | |||||
| Q_ASSERT(effect); | |||||
| if (self) | if (self) | ||||
| self->handleAudioMasterUpdateDisplay(); | self->handleAudioMasterUpdateDisplay(); | ||||
| else | |||||
| qWarning("VstPlugin::hostCallback::audioMasterUpdateDisplay called without valid object"); | |||||
| if (effect) | if (effect) | ||||
| effect->dispatcher(effect, effEditIdle, 0, 0, nullptr, 0.0f); | effect->dispatcher(effect, effEditIdle, 0, 0, nullptr, 0.0f); | ||||
| break; | break; | ||||
| @@ -328,8 +328,6 @@ private: | |||||
| #ifdef BUILD_BRIDGE_UI | #ifdef BUILD_BRIDGE_UI | ||||
| char* m_filename; | char* m_filename; | ||||
| void* m_lib; | void* m_lib; | ||||
| #else | |||||
| friend class CarlaPluginClient; | |||||
| #endif | #endif | ||||
| }; | }; | ||||
| @@ -32,22 +32,21 @@ | |||||
| #include <signal.h> | #include <signal.h> | ||||
| #endif | #endif | ||||
| static int qargc = 0; | |||||
| static char** qargv = nullptr; | |||||
| bool qcloseNow = false; | |||||
| static int qargc = 0; | |||||
| static char** qargv = nullptr; | |||||
| static bool qCloseNow = false; | |||||
| #if defined(Q_OS_UNIX) | #if defined(Q_OS_UNIX) | ||||
| void closeSignalHandler(int) | void closeSignalHandler(int) | ||||
| { | { | ||||
| qcloseNow = true; | |||||
| qCloseNow = true; | |||||
| } | } | ||||
| #elif defined(Q_OS_WIN) | #elif defined(Q_OS_WIN) | ||||
| BOOL WINAPI closeSignalHandler(DWORD dwCtrlType) | BOOL WINAPI closeSignalHandler(DWORD dwCtrlType) | ||||
| { | { | ||||
| if (dwCtrlType == CTRL_C_EVENT) | if (dwCtrlType == CTRL_C_EVENT) | ||||
| { | { | ||||
| qcloseNow = true; | |||||
| qCloseNow = true; | |||||
| return TRUE; | return TRUE; | ||||
| } | } | ||||
| @@ -77,29 +76,273 @@ void initSignalHandler() | |||||
| CARLA_BRIDGE_START_NAMESPACE | CARLA_BRIDGE_START_NAMESPACE | ||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| // client | |||||
| class CarlaPluginClient : public CarlaClient | |||||
| class BridgePluginGUI : public QDialog | |||||
| { | |||||
| public: | |||||
| class Callback | |||||
| { | |||||
| public: | |||||
| virtual ~Callback() {} | |||||
| virtual void guiClosedCallback() = 0; | |||||
| }; | |||||
| BridgePluginGUI(QWidget* const parent, Callback* const callback_, const char* const pluginName, const bool resizable) | |||||
| : QDialog(parent), | |||||
| callback(callback_) | |||||
| { | |||||
| qDebug("BridgePluginGUI::BridgePluginGUI(%p, %p, \"%s\", %s", parent, callback, pluginName, bool2str(resizable)); | |||||
| Q_ASSERT(callback); | |||||
| Q_ASSERT(pluginName); | |||||
| m_firstShow = true; | |||||
| m_resizable = resizable; | |||||
| vbLayout = new QVBoxLayout(this); | |||||
| vbLayout->setContentsMargins(0, 0, 0, 0); | |||||
| setLayout(vbLayout); | |||||
| container = new GuiContainer(this); | |||||
| vbLayout->addWidget(container); | |||||
| setNewSize(50, 50); | |||||
| setWindowTitle(QString("%1 (GUI)").arg(pluginName)); | |||||
| #ifdef Q_OS_WIN | |||||
| //if (! resizable) | |||||
| //setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint); | |||||
| #endif | |||||
| } | |||||
| ~BridgePluginGUI() | |||||
| { | |||||
| qDebug("BridgePluginGUI::~BridgePluginGUI()"); | |||||
| Q_ASSERT(container); | |||||
| Q_ASSERT(vbLayout); | |||||
| delete container; | |||||
| delete vbLayout; | |||||
| } | |||||
| GuiContainer* getContainer() | |||||
| { | |||||
| return container; | |||||
| } | |||||
| void setNewSize(int width, int height) | |||||
| { | |||||
| qDebug("BridgePluginGUI::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); | |||||
| container->setFixedSize(width, height); | |||||
| } | |||||
| } | |||||
| void setVisible(const bool yesNo) | |||||
| { | |||||
| qDebug("BridgePluginGUI::setVisible(%s)", bool2str(yesNo)); | |||||
| if (yesNo) | |||||
| { | |||||
| if (m_firstShow) | |||||
| { | |||||
| m_firstShow = false; | |||||
| restoreGeometry(QByteArray()); | |||||
| } | |||||
| else if (! m_geometry.isNull()) | |||||
| restoreGeometry(m_geometry); | |||||
| } | |||||
| else | |||||
| m_geometry = saveGeometry(); | |||||
| QDialog::setVisible(yesNo); | |||||
| } | |||||
| protected: | |||||
| void hideEvent(QHideEvent* const event) | |||||
| { | |||||
| qDebug("BridgePluginGUI::hideEvent(%p)", event); | |||||
| event->accept(); | |||||
| close(); | |||||
| } | |||||
| void closeEvent(QCloseEvent* const event) | |||||
| { | |||||
| qDebug("BridgePluginGUI::closeEvent(%p)", event); | |||||
| if (event->spontaneous()) | |||||
| callback->guiClosedCallback(); | |||||
| QDialog::closeEvent(event); | |||||
| } | |||||
| void done(int r) | |||||
| { | |||||
| QDialog::done(r); | |||||
| close(); | |||||
| } | |||||
| private: | |||||
| Callback* const callback; | |||||
| QVBoxLayout* vbLayout; | |||||
| GuiContainer* container; | |||||
| bool m_firstShow; | |||||
| bool m_resizable; | |||||
| QByteArray m_geometry; | |||||
| }; | |||||
| // ------------------------------------------------------------------------- | |||||
| class BridgePluginClient : public CarlaToolkit, | |||||
| public CarlaClient, | |||||
| public BridgePluginGUI::Callback, | |||||
| public QApplication | |||||
| { | { | ||||
| public: | public: | ||||
| CarlaPluginClient(CarlaToolkit* const toolkit) | |||||
| : CarlaClient(toolkit) | |||||
| BridgePluginClient() | |||||
| : CarlaToolkit("carla-bridge-plugin"), | |||||
| CarlaClient(this), | |||||
| QApplication(qargc, qargv) | |||||
| { | { | ||||
| engine = nullptr; | |||||
| plugin = nullptr; | |||||
| qDebug("BridgePluginClient::BridgePluginClient()"); | |||||
| msgTimer = 0; | |||||
| nextWidth = 0; | |||||
| nextHeight = 0; | |||||
| engine = nullptr; | |||||
| plugin = nullptr; | |||||
| pluginGui = nullptr; | |||||
| m_client = this; | |||||
| } | } | ||||
| ~CarlaPluginClient() | |||||
| ~BridgePluginClient() | |||||
| { | { | ||||
| qDebug("BridgePluginClient::~BridgePluginClient()"); | |||||
| Q_ASSERT(msgTimer == 0); | |||||
| Q_ASSERT(! pluginGui); | |||||
| } | } | ||||
| void setStuff(CarlaBackend::CarlaEngine* const engine_, CarlaBackend::CarlaPlugin* const plugin_) | |||||
| void setStuff(CarlaBackend::CarlaEngine* const engine, CarlaBackend::CarlaPlugin* const plugin) | |||||
| { | { | ||||
| Q_ASSERT(engine_); | |||||
| Q_ASSERT(plugin_); | |||||
| qDebug("BridgePluginClient::setStuff(%p, %p)", engine, plugin); | |||||
| Q_ASSERT(engine); | |||||
| Q_ASSERT(plugin); | |||||
| engine = engine_; | |||||
| plugin = plugin_; | |||||
| this->engine = engine; | |||||
| this->plugin = plugin; | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| // toolkit | |||||
| void init() | |||||
| { | |||||
| qDebug("BridgePluginClient::init()"); | |||||
| } | |||||
| void exec(CarlaClient* const, const bool showGui) | |||||
| { | |||||
| qDebug("BridgePluginClient::exec()"); | |||||
| if (showGui) | |||||
| { | |||||
| show(); | |||||
| } | |||||
| else | |||||
| { | |||||
| CarlaClient::sendOscUpdate(); | |||||
| CarlaClient::sendOscBridgeUpdate(); | |||||
| QApplication::setQuitOnLastWindowClosed(false); | |||||
| } | |||||
| msgTimer = startTimer(50); | |||||
| QApplication::exec(); | |||||
| } | |||||
| void quit() | |||||
| { | |||||
| qDebug("BridgePluginClient::quit()"); | |||||
| if (msgTimer != 0) | |||||
| { | |||||
| QApplication::killTimer(msgTimer); | |||||
| msgTimer = 0; | |||||
| } | |||||
| if (pluginGui) | |||||
| { | |||||
| if (pluginGui->isVisible()) | |||||
| hide(); | |||||
| pluginGui->close(); | |||||
| delete pluginGui; | |||||
| pluginGui = nullptr; | |||||
| } | |||||
| if (! QApplication::closingDown()) | |||||
| QApplication::quit(); | |||||
| } | |||||
| void show() | |||||
| { | |||||
| qDebug("BridgePluginClient::show()"); | |||||
| Q_ASSERT(pluginGui); | |||||
| if (plugin) | |||||
| plugin->showGui(true); | |||||
| if (pluginGui) | |||||
| pluginGui->show(); | |||||
| } | |||||
| void hide() | |||||
| { | |||||
| qDebug("BridgePluginClient::hide()"); | |||||
| Q_ASSERT(pluginGui); | |||||
| if (pluginGui) | |||||
| pluginGui->hide(); | |||||
| if (plugin) | |||||
| plugin->showGui(false); | |||||
| } | |||||
| void resize(int width, int height) | |||||
| { | |||||
| qDebug("BridgePluginClient::resize(%i, %i)", width, height); | |||||
| Q_ASSERT(pluginGui); | |||||
| if (pluginGui) | |||||
| pluginGui->setNewSize(width, height); | |||||
| } | |||||
| // --------------------------------------------------------------------- | |||||
| void createWindow(const bool resizable) | |||||
| { | |||||
| qDebug("BridgePluginClient::createWindow(%s)", bool2str(resizable)); | |||||
| Q_ASSERT(plugin); | |||||
| pluginGui = new BridgePluginGUI(nullptr, this, plugin->name(), resizable); | |||||
| plugin->setGuiContainer(pluginGui->getContainer()); | |||||
| } | } | ||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| @@ -262,30 +505,6 @@ public: | |||||
| #endif | #endif | ||||
| } | } | ||||
| // --------------------------------------------------------------------- | |||||
| // idle | |||||
| void idle() | |||||
| { | |||||
| Q_ASSERT(plugin); | |||||
| if (! plugin) | |||||
| return; | |||||
| plugin->idleGui(); | |||||
| } | |||||
| void showGui(const bool yesNo) | |||||
| { | |||||
| qDebug("CarlaPluginClient::showGui(%s)", bool2str(yesNo)); | |||||
| Q_ASSERT(plugin); | |||||
| if (! plugin) | |||||
| return; | |||||
| plugin->showGui(yesNo); | |||||
| } | |||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| // callback | // callback | ||||
| @@ -330,8 +549,9 @@ public: | |||||
| break; | break; | ||||
| case CarlaBackend::CALLBACK_RESIZE_GUI: | case CarlaBackend::CALLBACK_RESIZE_GUI: | ||||
| if (m_toolkit) | |||||
| m_toolkit->resize(value1, value2); | |||||
| Q_ASSERT(value1 > 0 && value2 > 0); | |||||
| nextWidth = value1; | |||||
| nextHeight = value2; | |||||
| break; | break; | ||||
| case CarlaBackend::CALLBACK_RELOAD_PARAMETERS: | case CarlaBackend::CALLBACK_RELOAD_PARAMETERS: | ||||
| @@ -345,7 +565,7 @@ public: | |||||
| break; | break; | ||||
| case CarlaBackend::CALLBACK_QUIT: | case CarlaBackend::CALLBACK_QUIT: | ||||
| //quequeMessage(MESSAGE_QUIT, 0, 0, 0.0); | |||||
| //QApplication::quit(); | |||||
| break; | break; | ||||
| default: | default: | ||||
| @@ -363,289 +583,55 @@ public: | |||||
| if (! ptr) | if (! ptr) | ||||
| return; | return; | ||||
| CarlaPluginClient* const client = (CarlaPluginClient*)ptr; | |||||
| client->handleCallback(action, value1, value2, value3); | |||||
| } | |||||
| private: | |||||
| CarlaBackend::CarlaEngine* engine; | |||||
| CarlaBackend::CarlaPlugin* plugin; | |||||
| }; | |||||
| // ------------------------------------------------------------------------- | |||||
| // toolkit | |||||
| class BridgeApplication : public QApplication | |||||
| { | |||||
| public: | |||||
| BridgeApplication() | |||||
| : QApplication(qargc, qargv) | |||||
| { | |||||
| msgTimer = 0; | |||||
| m_client = nullptr; | |||||
| } | |||||
| void exec(CarlaPluginClient* const client) | |||||
| { | |||||
| m_client = client; | |||||
| msgTimer = startTimer(50); | |||||
| QApplication::exec(); | |||||
| } | |||||
| void killMsgTimer() | |||||
| { | |||||
| Q_ASSERT(msgTimer != 0); | |||||
| killTimer(msgTimer); | |||||
| msgTimer = 0; | |||||
| BridgePluginClient* const _this_ = (BridgePluginClient*)ptr; | |||||
| _this_->handleCallback(action, value1, value2, value3); | |||||
| } | } | ||||
| void hideHostGUI() | |||||
| protected: | |||||
| void guiClosedCallback() | |||||
| { | { | ||||
| if (m_client) | |||||
| m_client->handleCallback(CarlaBackend::CALLBACK_SHOW_GUI, 0, 0, 0.0); | |||||
| } | } | ||||
| protected: | |||||
| void timerEvent(QTimerEvent* const event) | void timerEvent(QTimerEvent* const event) | ||||
| { | { | ||||
| if (qcloseNow) | |||||
| if (qCloseNow) | |||||
| return quit(); | return quit(); | ||||
| if (event->timerId() == msgTimer) | if (event->timerId() == msgTimer) | ||||
| { | { | ||||
| if (m_client) | |||||
| if (nextWidth > 0 && nextHeight > 0 && pluginGui) | |||||
| { | { | ||||
| m_client->idle(); | |||||
| if (! m_client->runMessages()) | |||||
| { | |||||
| msgTimer = 0; | |||||
| return; | |||||
| } | |||||
| pluginGui->setNewSize(nextWidth, nextHeight); | |||||
| nextWidth = 0; | |||||
| nextHeight = 0; | |||||
| } | } | ||||
| } | |||||
| QApplication::timerEvent(event); | |||||
| } | |||||
| private: | |||||
| int msgTimer; | |||||
| CarlaPluginClient* m_client; | |||||
| }; | |||||
| class BridgePluginGUI : public QDialog | |||||
| { | |||||
| public: | |||||
| BridgePluginGUI(QWidget* const parent, BridgeApplication* const app, const char* const pluginName, const bool resizable) | |||||
| : QDialog(parent), | |||||
| m_app(app), | |||||
| vbLayout(this) | |||||
| { | |||||
| m_firstShow = true; | |||||
| m_resizable = resizable; | |||||
| if (plugin) | |||||
| plugin->idleGui(); | |||||
| vbLayout.setContentsMargins(0, 0, 0, 0); | |||||
| setLayout(&vbLayout); | |||||
| setNewSize(50, 50); | |||||
| setWindowTitle(QString("%1 (GUI)").arg(pluginName)); | |||||
| #ifdef Q_OS_WIN | |||||
| if (! resizable) | |||||
| setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint); | |||||
| #endif | |||||
| } | |||||
| void setNewSize(int width, int height) | |||||
| { | |||||
| if (width < 30) | |||||
| width = 30; | |||||
| if (height < 30) | |||||
| height = 30; | |||||
| if (m_resizable) | |||||
| resize(width, height); | |||||
| else | |||||
| setFixedSize(width, height); | |||||
| } | |||||
| void setVisible(const bool yesNo) | |||||
| { | |||||
| if (yesNo) | |||||
| { | |||||
| if (m_firstShow) | |||||
| if (! CarlaClient::runMessages()) | |||||
| { | { | ||||
| m_firstShow = false; | |||||
| restoreGeometry(QByteArray()); | |||||
| Q_ASSERT(msgTimer == 0); | |||||
| msgTimer = 0; | |||||
| return; | |||||
| } | } | ||||
| else if (! m_geometry.isNull()) | |||||
| restoreGeometry(m_geometry); | |||||
| } | |||||
| else | |||||
| m_geometry = saveGeometry(); | |||||
| QDialog::setVisible(yesNo); | |||||
| } | |||||
| protected: | |||||
| void hideEvent(QHideEvent* const event) | |||||
| { | |||||
| // FIXME | |||||
| event->accept(); | |||||
| close(); | |||||
| m_app->hideHostGUI(); | |||||
| } | |||||
| void done(int r) | |||||
| { | |||||
| QDialog::done(r); | |||||
| close(); | |||||
| } | |||||
| private: | |||||
| BridgeApplication* const m_app; | |||||
| bool m_firstShow; | |||||
| bool m_resizable; | |||||
| QByteArray m_geometry; | |||||
| QVBoxLayout vbLayout; | |||||
| }; | |||||
| class CarlaToolkitPlugin : public CarlaToolkit | |||||
| { | |||||
| public: | |||||
| CarlaToolkitPlugin() | |||||
| : CarlaToolkit("carla-bridge-plugin") | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::CarlaToolkitPlugin()"); | |||||
| app = nullptr; | |||||
| gui = nullptr; | |||||
| } | |||||
| ~CarlaToolkitPlugin() | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::~CarlaToolkitPlugin()"); | |||||
| Q_ASSERT(! app); | |||||
| } | |||||
| void init() | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::init()"); | |||||
| Q_ASSERT(! app); | |||||
| app = new BridgeApplication; | |||||
| } | |||||
| void exec(CarlaClient* const client, const bool showGui) | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::exec(%p)", client); | |||||
| Q_ASSERT(app); | |||||
| Q_ASSERT(client); | |||||
| m_client = client; | |||||
| if (showGui) | |||||
| { | |||||
| show(); | |||||
| } | |||||
| else | |||||
| { | |||||
| m_client->sendOscUpdate(); | |||||
| m_client->sendOscBridgeUpdate(); | |||||
| app->setQuitOnLastWindowClosed(false); | |||||
| } | } | ||||
| app->exec((CarlaPluginClient*)client); | |||||
| } | |||||
| void quit() | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::quit()"); | |||||
| Q_ASSERT(app); | |||||
| if (gui) | |||||
| { | |||||
| gui->close(); | |||||
| delete gui; | |||||
| gui = nullptr; | |||||
| } | |||||
| if (app) | |||||
| { | |||||
| app->killMsgTimer(); | |||||
| if (! app->closingDown()) | |||||
| app->quit(); | |||||
| delete app; | |||||
| app = nullptr; | |||||
| } | |||||
| } | |||||
| void show() | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::show()"); | |||||
| if (m_client) | |||||
| ((CarlaPluginClient*)m_client)->showGui(true); | |||||
| if (gui) | |||||
| gui->show(); | |||||
| } | |||||
| void hide() | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::hide()"); | |||||
| if (gui) | |||||
| gui->hide(); | |||||
| if (m_client) | |||||
| ((CarlaPluginClient*)m_client)->showGui(false); | |||||
| } | |||||
| void resize(int width, int height) | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::resize(%i, %i)", width, height); | |||||
| Q_ASSERT(gui); | |||||
| if (! gui) | |||||
| return; | |||||
| gui->setNewSize(width, height); | |||||
| QApplication::timerEvent(event); | |||||
| } | } | ||||
| // --------------------------------------------------------------------- | // --------------------------------------------------------------------- | ||||
| void createWindow(const char* const pluginName, const bool resizable) | |||||
| { | |||||
| qDebug("CarlaToolkitPlugin::createWindow(%s, %s)", pluginName, bool2str(resizable)); | |||||
| Q_ASSERT(pluginName); | |||||
| gui = new BridgePluginGUI(nullptr, app, pluginName, resizable); | |||||
| } | |||||
| QDialog* getWindowHandle() const | |||||
| { | |||||
| return gui; | |||||
| } | |||||
| private: | |||||
| int msgTimer; | |||||
| int nextWidth, nextHeight; | |||||
| // --------------------------------------------------------------------- | |||||
| CarlaBackend::CarlaEngine* engine; | |||||
| CarlaBackend::CarlaPlugin* plugin; | |||||
| private: | |||||
| BridgeApplication* app; | |||||
| BridgePluginGUI* gui; | |||||
| BridgePluginGUI* pluginGui; | |||||
| }; | }; | ||||
| CarlaToolkit* CarlaToolkit::createNew(const char* const) | |||||
| { | |||||
| return new CarlaToolkitPlugin; | |||||
| } | |||||
| // ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||||
| CARLA_BRIDGE_END_NAMESPACE | CARLA_BRIDGE_END_NAMESPACE | ||||
| @@ -689,18 +675,15 @@ int main(int argc, char* argv[]) | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| // Init toolkit | |||||
| CarlaBridge::CarlaToolkitPlugin toolkit; | |||||
| toolkit.init(); | |||||
| // Init client | |||||
| CarlaBridge::CarlaPluginClient client(&toolkit); | |||||
| // Init bridge client | |||||
| CarlaBridge::BridgePluginClient client; | |||||
| client.init(); | |||||
| // Init OSC | // Init OSC | ||||
| if (useOsc && ! client.oscInit(oscUrl)) | if (useOsc && ! client.oscInit(oscUrl)) | ||||
| { | { | ||||
| toolkit.quit(); | |||||
| return -1; | |||||
| client.quit(); | |||||
| return -1; | |||||
| } | } | ||||
| // Init backend engine | // Init backend engine | ||||
| @@ -718,7 +701,7 @@ int main(int argc, char* argv[]) | |||||
| { | { | ||||
| qWarning("Bridge engine failed to start, error was:\n%s", CarlaBackend::getLastError()); | qWarning("Bridge engine failed to start, error was:\n%s", CarlaBackend::getLastError()); | ||||
| engine.close(); | engine.close(); | ||||
| toolkit.quit(); | |||||
| client.quit(); | |||||
| return 2; | return 2; | ||||
| } | } | ||||
| @@ -738,8 +721,7 @@ int main(int argc, char* argv[]) | |||||
| if (guiType == CarlaBackend::GUI_INTERNAL_QT4 || guiType == CarlaBackend::GUI_INTERNAL_COCOA || guiType == CarlaBackend::GUI_INTERNAL_HWND || guiType == CarlaBackend::GUI_INTERNAL_X11) | if (guiType == CarlaBackend::GUI_INTERNAL_QT4 || guiType == CarlaBackend::GUI_INTERNAL_COCOA || guiType == CarlaBackend::GUI_INTERNAL_HWND || guiType == CarlaBackend::GUI_INTERNAL_X11) | ||||
| { | { | ||||
| toolkit.createWindow(plugin->name(), guiResizable); | |||||
| plugin->setGuiData(toolkit.getWindowHandle()); | |||||
| client.createWindow(guiResizable); | |||||
| } | } | ||||
| if (! useOsc) | if (! useOsc) | ||||
| @@ -756,7 +738,7 @@ int main(int argc, char* argv[]) | |||||
| if (ret == 0) | if (ret == 0) | ||||
| { | { | ||||
| initSignalHandler(); | initSignalHandler(); | ||||
| toolkit.exec(&client, !useOsc); | |||||
| client.exec(nullptr, !useOsc); | |||||
| } | } | ||||
| engine.removeAllPlugins(); | engine.removeAllPlugins(); | ||||
| @@ -767,12 +749,12 @@ int main(int argc, char* argv[]) | |||||
| // Close OSC | // Close OSC | ||||
| client.sendOscExiting(); | client.sendOscExiting(); | ||||
| client.oscClose(); | client.oscClose(); | ||||
| // toolkit can't be closed manually, only by host | |||||
| // bridge client can't be closed manually, only by host | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| // Close toolkit | |||||
| toolkit.quit(); | |||||
| // Close bridge client | |||||
| client.quit(); | |||||
| } | } | ||||
| return ret; | return ret; | ||||
| @@ -57,7 +57,9 @@ public: | |||||
| virtual void hide() = 0; | virtual void hide() = 0; | ||||
| virtual void resize(int width, int height) = 0; | virtual void resize(int width, int height) = 0; | ||||
| #if BUILD_BRIDGE_UI | |||||
| static CarlaToolkit* createNew(const char* const title); | static CarlaToolkit* createNew(const char* const title); | ||||
| #endif | |||||
| protected: | protected: | ||||
| char* m_title; | char* m_title; | ||||
| @@ -878,8 +878,8 @@ class Host(object): | |||||
| self.lib.set_chunk_data.argtypes = [c_ushort, c_char_p] | self.lib.set_chunk_data.argtypes = [c_ushort, c_char_p] | ||||
| self.lib.set_chunk_data.restype = None | self.lib.set_chunk_data.restype = None | ||||
| self.lib.set_gui_data.argtypes = [c_ushort, c_uintptr] | |||||
| self.lib.set_gui_data.restype = None | |||||
| self.lib.set_gui_container.argtypes = [c_ushort, c_uintptr] | |||||
| self.lib.set_gui_container.restype = None | |||||
| self.lib.show_gui.argtypes = [c_ushort, c_bool] | self.lib.show_gui.argtypes = [c_ushort, c_bool] | ||||
| self.lib.show_gui.restype = None | self.lib.show_gui.restype = None | ||||
| @@ -1055,8 +1055,8 @@ class Host(object): | |||||
| def set_chunk_data(self, plugin_id, chunk_data): | def set_chunk_data(self, plugin_id, chunk_data): | ||||
| self.lib.set_chunk_data(plugin_id, chunk_data.encode("utf-8")) | self.lib.set_chunk_data(plugin_id, chunk_data.encode("utf-8")) | ||||
| def set_gui_data(self, plugin_id, gui_addr): | |||||
| self.lib.set_gui_data(plugin_id, gui_addr) | |||||
| def set_gui_container(self, plugin_id, gui_addr): | |||||
| self.lib.set_gui_container(plugin_id, gui_addr) | |||||
| def show_gui(self, plugin_id, yesno): | def show_gui(self, plugin_id, yesno): | ||||
| self.lib.show_gui(plugin_id, yesno) | self.lib.show_gui(plugin_id, yesno) | ||||
| @@ -24,6 +24,12 @@ from PyQt4.QtCore import pyqtSlot, Qt, QSettings, QTimer | |||||
| from PyQt4.QtGui import QColor, QCursor, QDialog, QFontMetrics, QFrame, QInputDialog, QMenu, QPainter, QVBoxLayout, QWidget | from PyQt4.QtGui import QColor, QCursor, QDialog, QFontMetrics, QFrame, QInputDialog, QMenu, QPainter, QVBoxLayout, QWidget | ||||
| from PyQt4.QtXml import QDomDocument | from PyQt4.QtXml import QDomDocument | ||||
| try: | |||||
| from PyQt4.QtGui import QX11EmbedContainer | |||||
| GuiContainer = QX11EmbedContainer | |||||
| except: | |||||
| GuiContainer = QWidget | |||||
| # Imports (Custom) | # Imports (Custom) | ||||
| import ui_carla_edit, ui_carla_parameter, ui_carla_plugin | import ui_carla_edit, ui_carla_parameter, ui_carla_plugin | ||||
| from shared import * | from shared import * | ||||
| @@ -1278,7 +1284,7 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget): | |||||
| self.gui_dialog = PluginGUI(self, self.m_pluginInfo['name'], guiInfo['resizable']) | self.gui_dialog = PluginGUI(self, self.m_pluginInfo['name'], guiInfo['resizable']) | ||||
| self.gui_dialog.hide() | self.gui_dialog.hide() | ||||
| Carla.Host.set_gui_data(self.m_pluginId, unwrapinstance(self.gui_dialog)) | |||||
| Carla.Host.set_gui_container(self.m_pluginId, unwrapinstance(self.gui_dialog.getContainer())) | |||||
| elif guiType in (GUI_EXTERNAL_LV2, GUI_EXTERNAL_SUIL, GUI_EXTERNAL_OSC): | elif guiType in (GUI_EXTERNAL_LV2, GUI_EXTERNAL_SUIL, GUI_EXTERNAL_OSC): | ||||
| pass | pass | ||||
| @@ -1988,19 +1994,24 @@ class PluginGUI(QDialog): | |||||
| QDialog.__init__(self, parent) | QDialog.__init__(self, parent) | ||||
| self.m_firstShow = True | self.m_firstShow = True | ||||
| self.m_geometry = None | |||||
| self.m_resizable = resizable | self.m_resizable = resizable | ||||
| self.m_geometry = None | |||||
| self.vbLayout = QVBoxLayout(self) | self.vbLayout = QVBoxLayout(self) | ||||
| self.vbLayout.setContentsMargins(0, 0, 0, 0) | self.vbLayout.setContentsMargins(0, 0, 0, 0) | ||||
| self.setLayout(self.vbLayout) | self.setLayout(self.vbLayout) | ||||
| self.container = GuiContainer(self) | |||||
| self.vbLayout.addWidget(self.container) | |||||
| self.setNewSize(50, 50) | self.setNewSize(50, 50) | ||||
| self.setWindowTitle("%s (GUI)" % pluginName) | self.setWindowTitle("%s (GUI)" % pluginName) | ||||
| if WINDOWS and not resizable: | if WINDOWS and not resizable: | ||||
| self.setWindowFlags(self.windowFlags() | Qt.MSWindowsFixedSizeDialogHint) | self.setWindowFlags(self.windowFlags() | Qt.MSWindowsFixedSizeDialogHint) | ||||
| self.connect(self, SIGNAL("finished(int)"), SLOT("slot_finished()")) | |||||
| def getContainer(self): | |||||
| return self.container | |||||
| def setNewSize(self, width, height): | def setNewSize(self, width, height): | ||||
| if width < 30: | if width < 30: | ||||
| @@ -2012,6 +2023,7 @@ class PluginGUI(QDialog): | |||||
| self.resize(width, height) | self.resize(width, height) | ||||
| else: | else: | ||||
| self.setFixedSize(width, height) | self.setFixedSize(width, height) | ||||
| self.container.setFixedSize(width, height) | |||||
| def setVisible(self, yesNo): | def setVisible(self, yesNo): | ||||
| if yesNo: | if yesNo: | ||||
| @@ -2025,15 +2037,16 @@ class PluginGUI(QDialog): | |||||
| QDialog.setVisible(self, yesNo) | QDialog.setVisible(self, yesNo) | ||||
| @pyqtSlot() | |||||
| def slot_finished(self): | |||||
| self.parent().b_gui.setChecked(False) | |||||
| def hideEvent(self, event): | def hideEvent(self, event): | ||||
| # FIXME | |||||
| event.accept() | event.accept() | ||||
| self.close() | self.close() | ||||
| def closeEvent(self, event): | |||||
| if event.spontaneous(): | |||||
| self.parent().b_gui.setChecked(False) | |||||
| QDialog.closeEvent(self, event) | |||||
| def done(self, r): | def done(self, r): | ||||
| QDialog.done(self, r) | QDialog.done(self, r) | ||||
| self.close() | self.close() | ||||