diff --git a/source/backend/engine/CarlaEngineBridge.cpp b/source/backend/engine/CarlaEngineBridge.cpp index 1546c6c2b..b88c5ddd0 100644 --- a/source/backend/engine/CarlaEngineBridge.cpp +++ b/source/backend/engine/CarlaEngineBridge.cpp @@ -1096,9 +1096,27 @@ public: plugin->showCustomUI(false); break; + case kPluginBridgeNonRtClientEmbedUI: { + const uint64_t winId = fShmNonRtClientControl.readULong(); + uint64_t resp = 0; + + if (plugin->isEnabled()) + resp = reinterpret_cast(plugin->embedCustomUI(reinterpret_cast(winId))); + + if (resp == 0) + resp = 1; + + const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); + + fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerEmbedUI); + fShmNonRtServerControl.writeULong(reinterpret_cast(resp)); + fShmNonRtServerControl.commitWrite(); + break; + } + case kPluginBridgeNonRtClientUiParameterChange: { - const uint32_t index(fShmNonRtClientControl.readUInt()); - const float value(fShmNonRtClientControl.readFloat()); + const uint32_t index = fShmNonRtClientControl.readUInt(); + const float value = fShmNonRtClientControl.readFloat(); if (plugin->isEnabled()) plugin->uiParameterChange(index, value); diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp index 25b11b030..c29d18b02 100644 --- a/source/backend/plugin/CarlaPluginBridge.cpp +++ b/source/backend/plugin/CarlaPluginBridge.cpp @@ -420,6 +420,7 @@ public: fTimedError(false), fBufferSize(engine->getBufferSize()), fProcWaitTime(0), + fPendingEmbedCustomUI(0), fBridgeBinary(), fBridgeThread(engine, this), fShmAudioPool(), @@ -1036,6 +1037,44 @@ public: #endif } + void* embedCustomUI(void* const ptr) override + { + if (fBridgeVersion < 9) + return nullptr; + + fPendingEmbedCustomUI = 0; + + { + const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex); + + fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientEmbedUI); + fShmNonRtClientControl.writeULong(reinterpret_cast(ptr)); + fShmNonRtClientControl.commitWrite(); + } + + const uint32_t timeoutEnd = Time::getMillisecondCounter() + 15*1000; // 15 secs + const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin; + + for (; Time::getMillisecondCounter() < timeoutEnd && fBridgeThread.isThreadRunning();) + { + pData->engine->callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); + + if (needsEngineIdle) + pData->engine->idle(); + + if (fPendingEmbedCustomUI != 0) + { + if (fPendingEmbedCustomUI == 1) + fPendingEmbedCustomUI = 0; + break; + } + + carla_msleep(20); + } + + return reinterpret_cast(fPendingEmbedCustomUI); + } + void idle() override { if (fBridgeThread.isThreadRunning()) @@ -2093,6 +2132,9 @@ public: pData->hints = hints | PLUGIN_IS_BRIDGE; pData->options = optionEn; + if (fBridgeVersion < 9) + pData->hints &= ~PLUGIN_HAS_CUSTOM_EMBED_UI; + fInfo.category = static_cast(category); fInfo.optionsAvailable = optionAv; } break; @@ -2520,6 +2562,10 @@ public: fSaved = true; break; + case kPluginBridgeNonRtServerEmbedUI: + fPendingEmbedCustomUI = fShmNonRtServerControl.readULong(); + break; + case kPluginBridgeNonRtServerUiClosed: #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->transientTryCounter = 0; @@ -2792,6 +2838,7 @@ private: bool fTimedError; uint fBufferSize; uint fProcWaitTime; + uint64_t fPendingEmbedCustomUI; CarlaString fBridgeBinary; CarlaPluginBridgeThread fBridgeThread; diff --git a/source/backend/plugin/CarlaPluginJack.cpp b/source/backend/plugin/CarlaPluginJack.cpp index 7ddc14035..01562b381 100644 --- a/source/backend/plugin/CarlaPluginJack.cpp +++ b/source/backend/plugin/CarlaPluginJack.cpp @@ -1533,6 +1533,7 @@ public: case kPluginBridgeNonRtServerMidiProgramData: case kPluginBridgeNonRtServerSetCustomData: case kPluginBridgeNonRtServerVersion: + case kPluginBridgeNonRtServerEmbedUI: break; case kPluginBridgeNonRtServerSetChunkDataFile: diff --git a/source/backend/plugin/CarlaPluginVST2.cpp b/source/backend/plugin/CarlaPluginVST2.cpp index fd6c73765..efe42e57b 100644 --- a/source/backend/plugin/CarlaPluginVST2.cpp +++ b/source/backend/plugin/CarlaPluginVST2.cpp @@ -1009,6 +1009,7 @@ public: #endif { pData->hints |= PLUGIN_HAS_CUSTOM_UI; + pData->hints |= PLUGIN_HAS_CUSTOM_EMBED_UI; } pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD; diff --git a/source/utils/CarlaBridgeDefines.hpp b/source/utils/CarlaBridgeDefines.hpp index b36d6a2d9..f83e5c668 100644 --- a/source/utils/CarlaBridgeDefines.hpp +++ b/source/utils/CarlaBridgeDefines.hpp @@ -24,7 +24,7 @@ #define CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM 6 // current API version, bumped when something is added -#define CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT 8 +#define CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT 9 // ------------------------------------------------------------------------------------------------------------------- @@ -79,6 +79,8 @@ enum PluginBridgeNonRtClientOpcode { kPluginBridgeNonRtClientSetOptions, // uint // stuff added in API 8 kPluginBridgeNonRtClientSetWindowTitle, // uint/size, str[] + // stuff added in API 9 + kPluginBridgeNonRtClientEmbedUI, // ulong }; // Client sends these to server during non-RT @@ -114,7 +116,9 @@ enum PluginBridgeNonRtServerOpcode { kPluginBridgeNonRtServerUiClosed, kPluginBridgeNonRtServerError, // uint/size, str[] // stuff added in API 7 - kPluginBridgeNonRtServerVersion // uint + kPluginBridgeNonRtServerVersion, // uint + // stuff added in API 9 + kPluginBridgeNonRtServerEmbedUI, // ulong }; // used for kPluginBridgeNonRtServerPortName diff --git a/source/utils/CarlaBridgeUtils.hpp b/source/utils/CarlaBridgeUtils.hpp index e8b9f506c..3ef6de902 100644 --- a/source/utils/CarlaBridgeUtils.hpp +++ b/source/utils/CarlaBridgeUtils.hpp @@ -127,6 +127,8 @@ const char* PluginBridgeNonRtClientOpcode2str(const PluginBridgeNonRtClientOpcod return "kPluginBridgeNonRtClientSetOptions"; case kPluginBridgeNonRtClientSetWindowTitle: return "kPluginBridgeNonRtClientSetWindowTitle"; + case kPluginBridgeNonRtClientEmbedUI: + return "kPluginBridgeNonRtClientEmbedUI"; } carla_stderr("CarlaBackend::PluginBridgeNonRtClientOpcode2str(%i) - invalid opcode", opcode); @@ -200,6 +202,8 @@ const char* PluginBridgeNonRtServerOpcode2str(const PluginBridgeNonRtServerOpcod return "kPluginBridgeNonRtServerError"; case kPluginBridgeNonRtServerVersion: return "kPluginBridgeNonRtServerVersion"; + case kPluginBridgeNonRtServerEmbedUI: + return "kPluginBridgeNonRtServerEmbedUI"; } carla_stderr("CarlaBackend::PluginBridgeNonRtServerOpcode2str%i) - invalid opcode", opcode);