| @@ -1146,6 +1146,7 @@ public: | |||
| void oscSend_bridge_set_custom_data(const char* const type, const char* const key, const char* const value) const noexcept; | |||
| void oscSend_bridge_set_chunk_data(const char* const chunkFile) const noexcept; | |||
| void oscSend_bridge_set_peaks() const noexcept; | |||
| void oscSend_bridge_pong() const noexcept; | |||
| #else | |||
| public: | |||
| void oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept; | |||
| @@ -928,7 +928,10 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, cons | |||
| } | |||
| if (plugin == nullptr) | |||
| { | |||
| pData->plugins[id].plugin = oldPlugin; | |||
| return false; | |||
| } | |||
| plugin->registerToOscClient(); | |||
| @@ -2497,6 +2500,19 @@ void CarlaEngine::oscSend_bridge_set_chunk_data(const char* const chunkFile) con | |||
| std::strcat(targetPath, "/bridge_set_chunk_data"); | |||
| try_lo_send(pData->oscData->target, targetPath, "s", chunkFile); | |||
| } | |||
| void CarlaEngine::oscSend_bridge_pong() const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||
| CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||
| CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||
| //carla_debug("CarlaEngine::oscSend_pong()"); | |||
| char targetPath[std::strlen(pData->oscData->path)+13]; | |||
| std::strcpy(targetPath, pData->oscData->path); | |||
| std::strcat(targetPath, "/bridge_pong"); | |||
| try_lo_send(pData->oscData->target, targetPath, ""); | |||
| } | |||
| #else | |||
| void CarlaEngine::oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept | |||
| { | |||
| @@ -1708,8 +1708,6 @@ private: | |||
| if (std::strcmp(clientName, thisClientName) == 0) | |||
| { | |||
| carla_stdout("CarlaEngineJack::findPluginIdAndIcon(\"%s\", ...) - found plugin, yes!!!", clientName); | |||
| pluginId = static_cast<int>(i); | |||
| icon = PATCHBAY_ICON_PLUGIN; | |||
| @@ -1731,7 +1729,6 @@ private: | |||
| return true; | |||
| } | |||
| } | |||
| carla_stdout("CarlaEngineJack::findPluginIdAndIcon(\"%s\", ...) - nothing here...", clientName); | |||
| return false; | |||
| } | |||
| @@ -147,8 +147,7 @@ void CarlaEngineOsc::close() | |||
| // ----------------------------------------------------------------------- | |||
| bool isDigit(const char c); | |||
| bool isDigit(const char c) | |||
| static bool isDigit(const char c) | |||
| { | |||
| return (c >= '0' && c <= '9'); | |||
| } | |||
| @@ -310,10 +309,12 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons | |||
| return handleMsgNoteOff(plugin, argc, argv, types); | |||
| // Plugin Bridges | |||
| if ((plugin->getHints() & PLUGIN_IS_BRIDGE) != 0 && std::strlen(method) > 11 && std::strncmp(method, "bridge_", 7) == 0) | |||
| if ((plugin->getHints() & PLUGIN_IS_BRIDGE) != 0 && std::strlen(method) >= 11 && std::strncmp(method, "bridge_", 7) == 0) | |||
| { | |||
| const char* const bmethod(method+7); | |||
| if (std::strcmp(bmethod, "pong") == 0) | |||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgePong, argc, argv, types); | |||
| if (std::strcmp(bmethod, "plugin_info1") == 0) | |||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgePluginInfo1, argc, argv, types); | |||
| if (std::strcmp(bmethod, "plugin_info2") == 0) | |||
| @@ -41,7 +41,7 @@ CarlaEngineThread::~CarlaEngineThread() | |||
| void CarlaEngineThread::run() | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,); | |||
| CARLA_ASSERT(fEngine->isRunning()); | |||
| CARLA_SAFE_ASSERT(fEngine->isRunning()); | |||
| carla_debug("CarlaEngineThread::run()"); | |||
| bool hasUi, oscRegisted, needsSingleThread; | |||
| @@ -102,7 +102,7 @@ void CarlaEngineThread::run() | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| // --------------------------------------------------- | |||
| // ------------------------------------------------------- | |||
| // Update OSC control client peaks | |||
| if (oscRegisted) | |||
| @@ -111,6 +111,13 @@ void CarlaEngineThread::run() | |||
| } | |||
| } | |||
| #ifdef BUILD_BRIDGE | |||
| // --------------------------------------------------------------- | |||
| // Send pong | |||
| fEngine->oscSend_bridge_pong(); | |||
| #endif | |||
| carla_msleep(25); | |||
| } | |||
| } | |||
| @@ -31,6 +31,8 @@ | |||
| #include <cmath> | |||
| #include <ctime> | |||
| #include <QtCore/QString> | |||
| #define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | |||
| /* check argument count */ \ | |||
| if (argc != argcToCompare) \ | |||
| @@ -221,8 +223,8 @@ struct BridgeControl : public RingBufferControl<StackRingBuffer> { | |||
| struct BridgeParamInfo { | |||
| float value; | |||
| CarlaString name; | |||
| CarlaString unit; | |||
| QString name; | |||
| QString unit; | |||
| BridgeParamInfo() | |||
| : value(0.0f) {} | |||
| @@ -244,6 +246,7 @@ public: | |||
| fSaved(false), | |||
| fNeedsSemDestroy(false), | |||
| fTimedOut(false), | |||
| fLastPongCounter(-1), | |||
| fParams(nullptr) | |||
| { | |||
| carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype)); | |||
| @@ -383,36 +386,36 @@ public: | |||
| void getLabel(char* const strBuf) const noexcept override | |||
| { | |||
| std::strncpy(strBuf, (const char*)fInfo.label, STR_MAX); | |||
| std::strncpy(strBuf, fInfo.label.getBuffer(), STR_MAX); | |||
| } | |||
| void getMaker(char* const strBuf) const noexcept override | |||
| { | |||
| std::strncpy(strBuf, (const char*)fInfo.maker, STR_MAX); | |||
| std::strncpy(strBuf, fInfo.maker.getBuffer(), STR_MAX); | |||
| } | |||
| void getCopyright(char* const strBuf) const noexcept override | |||
| { | |||
| std::strncpy(strBuf, (const char*)fInfo.copyright, STR_MAX); | |||
| std::strncpy(strBuf, fInfo.copyright.getBuffer(), STR_MAX); | |||
| } | |||
| void getRealName(char* const strBuf) const noexcept override | |||
| { | |||
| std::strncpy(strBuf, (const char*)fInfo.name, STR_MAX); | |||
| std::strncpy(strBuf, fInfo.name.getBuffer(), STR_MAX); | |||
| } | |||
| void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override | |||
| { | |||
| CARLA_ASSERT(parameterId < pData->param.count); | |||
| std::strncpy(strBuf, (const char*)fParams[parameterId].name, STR_MAX); | |||
| std::strncpy(strBuf, fParams[parameterId].name.toUtf8().constData(), STR_MAX); | |||
| } | |||
| void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override | |||
| { | |||
| CARLA_ASSERT(parameterId < pData->param.count); | |||
| std::strncpy(strBuf, (const char*)fParams[parameterId].unit, STR_MAX); | |||
| std::strncpy(strBuf, fParams[parameterId].unit.toUtf8().constData(), STR_MAX); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -1211,15 +1214,17 @@ public: | |||
| switch (infoType) | |||
| { | |||
| case kPluginBridgeNull: | |||
| case kPluginBridgePong: | |||
| if (fLastPongCounter > 0) | |||
| fLastPongCounter = 0; | |||
| break; | |||
| case kPluginBridgePluginInfo1: { | |||
| CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iih"); | |||
| const int32_t category = argv[0]->i; | |||
| const int32_t hints = argv[1]->i; | |||
| const int64_t uniqueId = argv[2]->h; | |||
| const int32_t category = argv[0]->i; | |||
| const int32_t hints = argv[1]->i; | |||
| const int64_t uniqueId = argv[2]->h; | |||
| CARLA_SAFE_ASSERT_BREAK(category >= 0); | |||
| CARLA_SAFE_ASSERT_BREAK(hints >= 0); | |||
| @@ -1301,7 +1306,7 @@ public: | |||
| fParams = nullptr; | |||
| } | |||
| CARLA_SAFE_ASSERT_INT2(ins+outs < static_cast<int32_t>(pData->engine->getOptions().maxParameters), ins+outs, pData->engine->getOptions().maxParameters); | |||
| CARLA_SAFE_ASSERT_INT2(ins+outs <= static_cast<int32_t>(pData->engine->getOptions().maxParameters), ins+outs, pData->engine->getOptions().maxParameters); | |||
| const uint32_t count(static_cast<uint32_t>(carla_min<int32_t>(ins+outs, static_cast<int32_t>(pData->engine->getOptions().maxParameters), 0))); | |||
| @@ -1784,13 +1789,18 @@ public: | |||
| pData->osc.thread.start(); | |||
| } | |||
| for (int i=0; i < 200; ++i) | |||
| fInitiated = false; | |||
| fLastPongCounter = 0; | |||
| for (; fLastPongCounter < 100; ++fLastPongCounter) | |||
| { | |||
| if (fInitiated || ! pData->osc.thread.isRunning()) | |||
| break; | |||
| carla_msleep(50); | |||
| } | |||
| fLastPongCounter = -1; | |||
| if (fInitError || ! fInitiated) | |||
| { | |||
| pData->osc.thread.stop(6000); | |||
| @@ -1835,6 +1845,8 @@ private: | |||
| bool fNeedsSemDestroy; | |||
| bool fTimedOut; | |||
| volatile int32_t fLastPongCounter; | |||
| CarlaString fBridgeBinary; | |||
| BridgeAudioPool fShmAudioPool; | |||
| @@ -1945,7 +1957,6 @@ CarlaPlugin* CarlaPlugin::newJACK(const Initializer& init) | |||
| if (! plugin->init(init.filename, init.name, init.label, nullptr)) | |||
| { | |||
| init.engine->registerEnginePlugin(init.id, nullptr); | |||
| delete plugin; | |||
| return nullptr; | |||
| } | |||
| @@ -1954,7 +1965,6 @@ CarlaPlugin* CarlaPlugin::newJACK(const Initializer& init) | |||
| if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && ! plugin->canRunInRack()) | |||
| { | |||
| init.engine->registerEnginePlugin(init.id, nullptr); | |||
| init.engine->setLastError("Carla's rack mode can only work with Stereo bridged apps, sorry!"); | |||
| delete plugin; | |||
| return nullptr; | |||
| @@ -198,7 +198,7 @@ public: | |||
| if (fWindow != nullptr) | |||
| { | |||
| String uiName(pData->name); | |||
| uiName += " (JUCE GUI)"; | |||
| uiName += " (GUI)"; | |||
| fWindow->setName(uiName); | |||
| } | |||
| } | |||
| @@ -233,7 +233,7 @@ public: | |||
| if (fWindow == nullptr) | |||
| { | |||
| String uiName(pData->name); | |||
| uiName += " (JUCE GUI)"; | |||
| uiName += " (GUI)"; | |||
| fWindow = new JucePluginWindow(); | |||
| fWindow->setName(uiName); | |||
| @@ -72,7 +72,7 @@ NativePlugin.cpp.o: NativePlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||
| BridgePlugin.cpp.o: BridgePlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_BACKEND_UTILS_HPP) $(CARLA_BRIDGE_UTILS_HPP) $(CARLA_MATH_UTILS_HPP) $(CARLA_SHM_UTILS_HPP) $(JACK_BRIDGE_HPP) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||
| LadspaPlugin.cpp.o: LadspaPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_LADSPA_UTILS_HPP) $(CARLA_MATH_UTILS_HPP) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| @@ -2073,6 +2073,9 @@ protected: | |||
| } | |||
| return ret; | |||
| // unused | |||
| (void)opt; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -301,7 +301,7 @@ lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size) | |||
| if (forge->sink) { | |||
| out = forge->sink(forge->handle, data, size); | |||
| } else { | |||
| out = (LV2_Atom_Forge_Ref)forge->buf + forge->offset; | |||
| out = (LV2_Atom_Forge_Ref)forge->buf + (LV2_Atom_Forge_Ref)forge->offset; | |||
| uint8_t* mem = forge->buf + forge->offset; | |||
| if (forge->offset + size > forge->size) { | |||
| return 0; | |||
| @@ -24,7 +24,7 @@ | |||
| // ----------------------------------------------------------------------- | |||
| enum PluginBridgeInfoType { | |||
| kPluginBridgeNull = 0, | |||
| kPluginBridgePong = 0, | |||
| kPluginBridgePluginInfo1, // uuh => category, hints, uniqueId | |||
| kPluginBridgePluginInfo2, // ssss => realName, label, maker, copyright | |||
| kPluginBridgeAudioCount, // uu => ins, outs | |||
| @@ -94,8 +94,8 @@ const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type) noexcept | |||
| { | |||
| switch (type) | |||
| { | |||
| case kPluginBridgeNull: | |||
| return "kPluginBridgeNull"; | |||
| case kPluginBridgePong: | |||
| return "kPluginBridgePong"; | |||
| case kPluginBridgePluginInfo1: | |||
| return "kPluginBridgePluginInfo1"; | |||
| case kPluginBridgePluginInfo2: | |||