From 01c1aed7616f53014a8421831a8458c86cdd8985 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 27 Jun 2020 21:37:03 +0100 Subject: [PATCH] Convert from and to client name prefix as needed Signed-off-by: falkTX --- source/backend/CarlaEngine.hpp | 3 +- source/backend/engine/CarlaEngine.cpp | 151 +++++++++++++-------- source/backend/engine/CarlaEngineGraph.cpp | 12 +- source/backend/engine/CarlaEngineJack.cpp | 28 ++-- 4 files changed, 118 insertions(+), 76 deletions(-) diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index 0e0eab07e..4c302bd00 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -1368,7 +1368,8 @@ protected: virtual const char* const* getPatchbayConnections(bool external) const; virtual const PatchbayPosition* getPatchbayPositions(bool external, uint& count) const; virtual void restorePatchbayConnection(bool external, const char* sourcePort, const char* targetPort); - virtual void restorePatchbayGroupPosition(bool external, const PatchbayPosition& ppos); + // returns true if plugin name mapping found, ppos.name updated to its converted name + virtual bool restorePatchbayGroupPosition(bool external, PatchbayPosition& ppos); /*! * Virtual functions for handling external graph ports. diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index 7292eced6..4c42ceca7 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -44,6 +44,8 @@ #include "water/xml/XmlDocument.h" #include "water/xml/XmlElement.h" +#include + // FIXME Remove on 2.1 release #include "lv2/atom.h" @@ -2355,14 +2357,6 @@ void CarlaEngine::saveProjectInternal(water::MemoryOutputStream& outStream) cons { saveExternalConnections = false; } - else if (std::getenv("LADISH_APP_NAME") != nullptr) - { - saveExternalConnections = false; - } - else if (std::getenv("NSM_URL") != nullptr) - { - saveExternalConnections = false; - } else { saveExternalConnections = true; @@ -2524,6 +2518,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw if (carla_isEqual(xmlElement->getDoubleAttribute("VERSION", 0.0), 2.0) || xmlElement->getBoolAttribute("IgnoreClientPrefix", false)) { + carla_stdout("Loading project in compatibility mode, will ignore client name prefix"); pData->ignoreClientPrefix = true; setOption(ENGINE_OPTION_CLIENT_NAME_PREFIX, 0, ""); } @@ -2952,40 +2947,45 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw return false; } - bool hasInternalConnections = false; + // now we handle positions + std::map mapGroupNamesInternal, mapGroupNamesExternal; - // and now we handle connections (internal) - if (XmlElement* const elem = xmlElement->getChildByName("Patchbay")) + if (XmlElement* const elemPatchbay = xmlElement->getChildByName("Patchbay")) { - hasInternalConnections = true; - - if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) + if (XmlElement* const elemPositions = elemPatchbay->getChildByName("Positions")) { - CarlaString sourcePort, targetPort; + String name; + PatchbayPosition ppos = { nullptr, -1, 0, 0, 0, 0, false }; - for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement()) + for (XmlElement* patchElem = elemPositions->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement()) { const String& patchTag(patchElem->getTagName()); - if (patchTag != "Connection") + if (patchTag != "Position") continue; - sourcePort.clear(); - targetPort.clear(); + XmlElement* const patchName = patchElem->getChildByName("Name"); + CARLA_SAFE_ASSERT_CONTINUE(patchName != nullptr); - for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement()) + const String nameText(patchName->getAllSubText().trim()); + name = xmlSafeString(nameText, false); + + ppos.name = name.toRawUTF8(); + ppos.x1 = patchElem->getIntAttribute("x1"); + ppos.y1 = patchElem->getIntAttribute("y1"); + ppos.x2 = patchElem->getIntAttribute("x2"); + ppos.y2 = patchElem->getIntAttribute("y2"); + ppos.pluginId = patchElem->getIntAttribute("pluginId", -1); + ppos.dealloc = false; + + if (name.isNotEmpty() && restorePatchbayGroupPosition(false, ppos)) { - const String& tag(connElem->getTagName()); - const String text(connElem->getAllSubText().trim()); + carla_stdout("Converted client name '%s' to '%s' for this session", name.toRawUTF8(), ppos.name); + mapGroupNamesInternal[name] = ppos.name; - /**/ if (tag == "Source") - sourcePort = xmlSafeString(text, false).toRawUTF8(); - else if (tag == "Target") - targetPort = xmlSafeString(text, false).toRawUTF8(); + if (ppos.dealloc) + std::free(const_cast(ppos.name)); } - - if (sourcePort.isNotEmpty() && targetPort.isNotEmpty()) - restorePatchbayConnection(false, sourcePort, targetPort); } callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); @@ -3001,8 +3001,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw } } - // now we handle positions - if (XmlElement* const elemPatchbay = xmlElement->getChildByName("Patchbay")) + if (XmlElement* const elemPatchbay = xmlElement->getChildByName("ExternalPatchbay")) { if (XmlElement* const elemPositions = elemPatchbay->getChildByName("Positions")) { @@ -3028,9 +3027,16 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw ppos.x2 = patchElem->getIntAttribute("x2"); ppos.y2 = patchElem->getIntAttribute("y2"); ppos.pluginId = patchElem->getIntAttribute("pluginId", -1); + ppos.dealloc = false; + + if (name.isNotEmpty() && restorePatchbayGroupPosition(true, ppos)) + { + carla_stdout("Converted client name '%s' to '%s' for this session", name.toRawUTF8(), ppos.name); + mapGroupNamesExternal[name] = ppos.name; - if (name.isNotEmpty()) - restorePatchbayGroupPosition(false, ppos); + if (ppos.dealloc) + std::free(const_cast(ppos.name)); + } } callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); @@ -3046,35 +3052,60 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw } } - if (XmlElement* const elemPatchbay = xmlElement->getChildByName("ExternalPatchbay")) + bool hasInternalConnections = false; + + // and now we handle connections (internal) + if (XmlElement* const elem = xmlElement->getChildByName("Patchbay")) { - if (XmlElement* const elemPositions = elemPatchbay->getChildByName("Positions")) + hasInternalConnections = true; + + if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { - String name; - PatchbayPosition ppos = { nullptr, -1, 0, 0, 0, 0, false }; + water::String sourcePort, targetPort; - for (XmlElement* patchElem = elemPositions->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement()) + for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement()) { const String& patchTag(patchElem->getTagName()); - if (patchTag != "Position") + if (patchTag != "Connection") continue; - XmlElement* const patchName = patchElem->getChildByName("Name"); - CARLA_SAFE_ASSERT_CONTINUE(patchName != nullptr); + sourcePort.clear(); + targetPort.clear(); - const String nameText(patchName->getAllSubText().trim()); - name = xmlSafeString(nameText, false); + for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement()) + { + const String& tag(connElem->getTagName()); + const String text(connElem->getAllSubText().trim()); - ppos.name = name.toRawUTF8(); - ppos.x1 = patchElem->getIntAttribute("x1"); - ppos.y1 = patchElem->getIntAttribute("y1"); - ppos.x2 = patchElem->getIntAttribute("x2"); - ppos.y2 = patchElem->getIntAttribute("y2"); - ppos.pluginId = patchElem->getIntAttribute("pluginId", -1); + /**/ if (tag == "Source") + sourcePort = xmlSafeString(text, false); + else if (tag == "Target") + targetPort = xmlSafeString(text, false); + } - if (name.isNotEmpty()) - restorePatchbayGroupPosition(true, ppos); + if (sourcePort.isNotEmpty() && targetPort.isNotEmpty()) + { + std::map& map(mapGroupNamesInternal); + std::map::iterator it; + if ((it = map.find(sourcePort.upToFirstOccurrenceOf(":", false, false))) != map.end()) + sourcePort = it->second + sourcePort.fromFirstOccurrenceOf(":", true, false); + if ((it = map.find(targetPort.upToFirstOccurrenceOf(":", false, false))) != map.end()) + targetPort = it->second + targetPort.fromFirstOccurrenceOf(":", true, false); + + restorePatchbayConnection(false, sourcePort.toRawUTF8(), targetPort.toRawUTF8()); + } + } + + callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr); + + if (pData->aboutToClose) + return true; + + if (pData->actionCanceled) + { + setLastError("Project load canceled"); + return false; } } } @@ -3127,7 +3158,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw continue; } - CarlaString sourcePort, targetPort; + water::String sourcePort, targetPort; for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement()) { @@ -3145,13 +3176,23 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw const String text(connElem->getAllSubText().trim()); /**/ if (tag == "Source") - sourcePort = xmlSafeString(text, false).toRawUTF8(); + sourcePort = xmlSafeString(text, false); else if (tag == "Target") - targetPort = xmlSafeString(text, false).toRawUTF8(); + targetPort = xmlSafeString(text, false); } if (sourcePort.isNotEmpty() && targetPort.isNotEmpty()) - restorePatchbayConnection(loadingAsExternal, sourcePort, targetPort); + { + std::map& map(loadingAsExternal ? mapGroupNamesExternal + : mapGroupNamesInternal); + std::map::iterator it; + if ((it = map.find(sourcePort.upToFirstOccurrenceOf(":", false, false))) != map.end()) + sourcePort = it->second + sourcePort.fromFirstOccurrenceOf(":", true, false); + if ((it = map.find(targetPort.upToFirstOccurrenceOf(":", false, false))) != map.end()) + targetPort = it->second + targetPort.fromFirstOccurrenceOf(":", true, false); + + restorePatchbayConnection(loadingAsExternal, sourcePort.toRawUTF8(), targetPort.toRawUTF8()); + } } break; } diff --git a/source/backend/engine/CarlaEngineGraph.cpp b/source/backend/engine/CarlaEngineGraph.cpp index ae3e50d33..feb1b7996 100644 --- a/source/backend/engine/CarlaEngineGraph.cpp +++ b/source/backend/engine/CarlaEngineGraph.cpp @@ -2958,21 +2958,23 @@ void CarlaEngine::restorePatchbayConnection(const bool external, } } -void CarlaEngine::restorePatchbayGroupPosition(const bool external, const PatchbayPosition& ppos) +bool CarlaEngine::restorePatchbayGroupPosition(const bool external, PatchbayPosition& ppos) { - CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(),); - CARLA_SAFE_ASSERT_RETURN(ppos.name != nullptr && ppos.name[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), false); + CARLA_SAFE_ASSERT_RETURN(ppos.name != nullptr && ppos.name[0] != '\0', false); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) { PatchbayGraph* const graph = pData->graph.getPatchbayGraph(); - CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); + CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); uint groupId; - CARLA_SAFE_ASSERT_RETURN(graph->getGroupFromName(external, ppos.name, groupId),); + CARLA_SAFE_ASSERT_RETURN(graph->getGroupFromName(external, ppos.name, groupId), false); graph->setGroupPos(true, true, external, groupId, ppos.x1, ppos.y1, ppos.x2, ppos.y2); } + + return false; } // ----------------------------------------------------------------------- diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index 2e76c81e9..eb35d9e9d 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -2681,18 +2681,17 @@ public: } } - void restorePatchbayGroupPosition(const bool external, const PatchbayPosition& ppos) override + bool restorePatchbayGroupPosition(const bool external, PatchbayPosition& ppos) override { - CARLA_SAFE_ASSERT_RETURN(fClient != nullptr,); + CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false); carla_debug("CarlaEngineJack::restorePatchbayGroupPosition(%s, ...)", bool2str(external)); if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! external) return CarlaEngine::restorePatchbayGroupPosition(external, ppos); - bool reallocd = false; bool hasGroups = true; uint groupId = 0; - const char* rname = ppos.name; + const char* const orig_name = ppos.name; /* NOTE: When loading a project, it might take a bit to receive plugins' jack client registration callbacks. * We try to wait a little for it, but not too much. @@ -2700,18 +2699,18 @@ public: if (ppos.pluginId >= 0) { // strip client name prefix if already in place - if (const char* const rname2 = std::strstr(rname, ".")) + if (const char* const rname2 = std::strstr(ppos.name, ".")) if (const char* const rname3 = std::strstr(rname2, "/")) - rname = rname3 + 1; + ppos.name = rname3 + 1; if (fClientNamePrefix.isNotEmpty()) { - char* nname = (char*)std::malloc(fClientNamePrefix.length() + std::strlen(rname) + 1); + char* nname = (char*)std::malloc(fClientNamePrefix.length() + std::strlen(ppos.name) + 1); std::strcpy(nname, fClientNamePrefix.buffer()); - std::strcat(nname, rname); + std::strcat(nname, ppos.name); - reallocd = true; - rname = nname; + ppos.name = nname; + ppos.dealloc = true; } for (int i=10; --i >=0;) @@ -2725,7 +2724,7 @@ public: break; } - groupId = fUsedGroups.getGroupId(rname); + groupId = fUsedGroups.getGroupId(ppos.name); } if (groupId != 0) @@ -2740,7 +2739,7 @@ public: const CarlaMutexLocker cml(fUsedGroups.mutex); if (fUsedGroups.list.count() != 0) - groupId = fUsedGroups.getGroupId(rname); + groupId = fUsedGroups.getGroupId(ppos.name); else hasGroups = false; } @@ -2755,7 +2754,7 @@ public: jack_uuid_t uuid; { - char* const uuidstr = jackbridge_get_uuid_for_client_name(fClient, rname); + char* const uuidstr = jackbridge_get_uuid_for_client_name(fClient, ppos.name); CARLA_SAFE_ASSERT_BREAK(uuidstr != nullptr && uuidstr[0] != '\0'); const bool parsed = jackbridge_uuid_parse(uuidstr, &uuid); @@ -2784,8 +2783,7 @@ public: } # endif - if (reallocd) - std::free(const_cast(rname)); + return ppos.name != orig_name; } #endif