| @@ -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_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_chunk_data(const char* const chunkFile) const noexcept; | ||||
| void oscSend_bridge_set_peaks() const noexcept; | void oscSend_bridge_set_peaks() const noexcept; | ||||
| void oscSend_bridge_pong() const noexcept; | |||||
| #else | #else | ||||
| public: | public: | ||||
| void oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept; | 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) | if (plugin == nullptr) | ||||
| { | |||||
| pData->plugins[id].plugin = oldPlugin; | |||||
| return false; | return false; | ||||
| } | |||||
| plugin->registerToOscClient(); | 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"); | std::strcat(targetPath, "/bridge_set_chunk_data"); | ||||
| try_lo_send(pData->oscData->target, targetPath, "s", chunkFile); | 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 | #else | ||||
| void CarlaEngine::oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept | 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) | if (std::strcmp(clientName, thisClientName) == 0) | ||||
| { | { | ||||
| carla_stdout("CarlaEngineJack::findPluginIdAndIcon(\"%s\", ...) - found plugin, yes!!!", clientName); | |||||
| pluginId = static_cast<int>(i); | pluginId = static_cast<int>(i); | ||||
| icon = PATCHBAY_ICON_PLUGIN; | icon = PATCHBAY_ICON_PLUGIN; | ||||
| @@ -1731,7 +1729,6 @@ private: | |||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| carla_stdout("CarlaEngineJack::findPluginIdAndIcon(\"%s\", ...) - nothing here...", clientName); | |||||
| return false; | 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'); | 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); | return handleMsgNoteOff(plugin, argc, argv, types); | ||||
| // Plugin Bridges | // 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); | 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) | if (std::strcmp(bmethod, "plugin_info1") == 0) | ||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgePluginInfo1, argc, argv, types); | return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgePluginInfo1, argc, argv, types); | ||||
| if (std::strcmp(bmethod, "plugin_info2") == 0) | if (std::strcmp(bmethod, "plugin_info2") == 0) | ||||
| @@ -41,7 +41,7 @@ CarlaEngineThread::~CarlaEngineThread() | |||||
| void CarlaEngineThread::run() | void CarlaEngineThread::run() | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,); | ||||
| CARLA_ASSERT(fEngine->isRunning()); | |||||
| CARLA_SAFE_ASSERT(fEngine->isRunning()); | |||||
| carla_debug("CarlaEngineThread::run()"); | carla_debug("CarlaEngineThread::run()"); | ||||
| bool hasUi, oscRegisted, needsSingleThread; | bool hasUi, oscRegisted, needsSingleThread; | ||||
| @@ -102,7 +102,7 @@ void CarlaEngineThread::run() | |||||
| } | } | ||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // --------------------------------------------------- | |||||
| // ------------------------------------------------------- | |||||
| // Update OSC control client peaks | // Update OSC control client peaks | ||||
| if (oscRegisted) | if (oscRegisted) | ||||
| @@ -111,6 +111,13 @@ void CarlaEngineThread::run() | |||||
| } | } | ||||
| } | } | ||||
| #ifdef BUILD_BRIDGE | |||||
| // --------------------------------------------------------------- | |||||
| // Send pong | |||||
| fEngine->oscSend_bridge_pong(); | |||||
| #endif | |||||
| carla_msleep(25); | carla_msleep(25); | ||||
| } | } | ||||
| } | } | ||||
| @@ -31,6 +31,8 @@ | |||||
| #include <cmath> | #include <cmath> | ||||
| #include <ctime> | #include <ctime> | ||||
| #include <QtCore/QString> | |||||
| #define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | #define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | ||||
| /* check argument count */ \ | /* check argument count */ \ | ||||
| if (argc != argcToCompare) \ | if (argc != argcToCompare) \ | ||||
| @@ -221,8 +223,8 @@ struct BridgeControl : public RingBufferControl<StackRingBuffer> { | |||||
| struct BridgeParamInfo { | struct BridgeParamInfo { | ||||
| float value; | float value; | ||||
| CarlaString name; | |||||
| CarlaString unit; | |||||
| QString name; | |||||
| QString unit; | |||||
| BridgeParamInfo() | BridgeParamInfo() | ||||
| : value(0.0f) {} | : value(0.0f) {} | ||||
| @@ -244,6 +246,7 @@ public: | |||||
| fSaved(false), | fSaved(false), | ||||
| fNeedsSemDestroy(false), | fNeedsSemDestroy(false), | ||||
| fTimedOut(false), | fTimedOut(false), | ||||
| fLastPongCounter(-1), | |||||
| fParams(nullptr) | fParams(nullptr) | ||||
| { | { | ||||
| carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype)); | 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 | 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 | 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 | 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 | 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 | void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override | ||||
| { | { | ||||
| CARLA_ASSERT(parameterId < pData->param.count); | 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 | void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override | ||||
| { | { | ||||
| CARLA_ASSERT(parameterId < pData->param.count); | 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) | switch (infoType) | ||||
| { | { | ||||
| case kPluginBridgeNull: | |||||
| case kPluginBridgePong: | |||||
| if (fLastPongCounter > 0) | |||||
| fLastPongCounter = 0; | |||||
| break; | break; | ||||
| case kPluginBridgePluginInfo1: { | case kPluginBridgePluginInfo1: { | ||||
| CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iih"); | 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(category >= 0); | ||||
| CARLA_SAFE_ASSERT_BREAK(hints >= 0); | CARLA_SAFE_ASSERT_BREAK(hints >= 0); | ||||
| @@ -1301,7 +1306,7 @@ public: | |||||
| fParams = nullptr; | 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))); | 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(); | 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()) | if (fInitiated || ! pData->osc.thread.isRunning()) | ||||
| break; | break; | ||||
| carla_msleep(50); | carla_msleep(50); | ||||
| } | } | ||||
| fLastPongCounter = -1; | |||||
| if (fInitError || ! fInitiated) | if (fInitError || ! fInitiated) | ||||
| { | { | ||||
| pData->osc.thread.stop(6000); | pData->osc.thread.stop(6000); | ||||
| @@ -1835,6 +1845,8 @@ private: | |||||
| bool fNeedsSemDestroy; | bool fNeedsSemDestroy; | ||||
| bool fTimedOut; | bool fTimedOut; | ||||
| volatile int32_t fLastPongCounter; | |||||
| CarlaString fBridgeBinary; | CarlaString fBridgeBinary; | ||||
| BridgeAudioPool fShmAudioPool; | BridgeAudioPool fShmAudioPool; | ||||
| @@ -1945,7 +1957,6 @@ CarlaPlugin* CarlaPlugin::newJACK(const Initializer& init) | |||||
| if (! plugin->init(init.filename, init.name, init.label, nullptr)) | if (! plugin->init(init.filename, init.name, init.label, nullptr)) | ||||
| { | { | ||||
| init.engine->registerEnginePlugin(init.id, nullptr); | |||||
| delete plugin; | delete plugin; | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -1954,7 +1965,6 @@ CarlaPlugin* CarlaPlugin::newJACK(const Initializer& init) | |||||
| if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && ! plugin->canRunInRack()) | 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!"); | init.engine->setLastError("Carla's rack mode can only work with Stereo bridged apps, sorry!"); | ||||
| delete plugin; | delete plugin; | ||||
| return nullptr; | return nullptr; | ||||
| @@ -198,7 +198,7 @@ public: | |||||
| if (fWindow != nullptr) | if (fWindow != nullptr) | ||||
| { | { | ||||
| String uiName(pData->name); | String uiName(pData->name); | ||||
| uiName += " (JUCE GUI)"; | |||||
| uiName += " (GUI)"; | |||||
| fWindow->setName(uiName); | fWindow->setName(uiName); | ||||
| } | } | ||||
| } | } | ||||
| @@ -233,7 +233,7 @@ public: | |||||
| if (fWindow == nullptr) | if (fWindow == nullptr) | ||||
| { | { | ||||
| String uiName(pData->name); | String uiName(pData->name); | ||||
| uiName += " (JUCE GUI)"; | |||||
| uiName += " (GUI)"; | |||||
| fWindow = new JucePluginWindow(); | fWindow = new JucePluginWindow(); | ||||
| fWindow->setName(uiName); | 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 $@ | $(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) | 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) | 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 $@ | $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | ||||
| @@ -2073,6 +2073,9 @@ protected: | |||||
| } | } | ||||
| return ret; | 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) { | if (forge->sink) { | ||||
| out = forge->sink(forge->handle, data, size); | out = forge->sink(forge->handle, data, size); | ||||
| } else { | } 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; | uint8_t* mem = forge->buf + forge->offset; | ||||
| if (forge->offset + size > forge->size) { | if (forge->offset + size > forge->size) { | ||||
| return 0; | return 0; | ||||
| @@ -24,7 +24,7 @@ | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| enum PluginBridgeInfoType { | enum PluginBridgeInfoType { | ||||
| kPluginBridgeNull = 0, | |||||
| kPluginBridgePong = 0, | |||||
| kPluginBridgePluginInfo1, // uuh => category, hints, uniqueId | kPluginBridgePluginInfo1, // uuh => category, hints, uniqueId | ||||
| kPluginBridgePluginInfo2, // ssss => realName, label, maker, copyright | kPluginBridgePluginInfo2, // ssss => realName, label, maker, copyright | ||||
| kPluginBridgeAudioCount, // uu => ins, outs | kPluginBridgeAudioCount, // uu => ins, outs | ||||
| @@ -94,8 +94,8 @@ const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type) noexcept | |||||
| { | { | ||||
| switch (type) | switch (type) | ||||
| { | { | ||||
| case kPluginBridgeNull: | |||||
| return "kPluginBridgeNull"; | |||||
| case kPluginBridgePong: | |||||
| return "kPluginBridgePong"; | |||||
| case kPluginBridgePluginInfo1: | case kPluginBridgePluginInfo1: | ||||
| return "kPluginBridgePluginInfo1"; | return "kPluginBridgePluginInfo1"; | ||||
| case kPluginBridgePluginInfo2: | case kPluginBridgePluginInfo2: | ||||