From 250c9772a000b35d75cf739202ca85bb25627540 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 22 Feb 2015 11:02:45 +0000 Subject: [PATCH] Initial code to save external connections This is going to be needed for rtaudio/juce patchbay modes, but it's also nice to have for JACK. --- source/backend/CarlaEngine.hpp | 4 +- source/backend/engine/CarlaEngine.cpp | 95 ++++++++++++++++++---- source/backend/engine/CarlaEngineGraph.cpp | 19 +++-- source/backend/engine/CarlaEngineGraph.hpp | 2 +- source/backend/engine/CarlaEngineJack.cpp | 14 ++-- 5 files changed, 103 insertions(+), 31 deletions(-) diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index 7168326d3..7bc24c91c 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -1121,8 +1121,8 @@ protected: * Virtual functions for handling patchbay state. * Do not free returned data. */ - virtual const char* const* getPatchbayConnections() const; - virtual void restorePatchbayConnection(const char* const sourcePort, const char* const targetPort); + virtual const char* const* getPatchbayConnections(const bool external) const; + virtual void restorePatchbayConnection(const bool external, const char* const sourcePort, const char* const targetPort); #endif // ------------------------------------------------------------------- diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index 7c78d29d5..80de59ffd 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -1657,28 +1657,55 @@ void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStream) const plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, "__CarlaPingOnOff__", "true", false); } - bool saveConnections = true; + bool saveExternalConnections = true; + // save internal connections + if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) + { + if (const char* const* const patchbayConns = getPatchbayConnections(false)) + { + MemoryOutputStream outPatchbay(2048); + + outPatchbay << "\n \n"; + + for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i ) + { + const char* const connSource(patchbayConns[i]); + const char* const connTarget(patchbayConns[i+1]); + + CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0'); + CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0'); + + outPatchbay << " \n"; + outPatchbay << " " << connSource << "\n"; + outPatchbay << " " << connTarget << "\n"; + outPatchbay << " \n"; + } + + outPatchbay << " \n"; + outStream << outPatchbay; + } + } // if we're running inside some session-manager, let them handle the connections - if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY) + else { /**/ if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr) - saveConnections = false; + saveExternalConnections = false; else if (std::getenv("LADISH_APP_NAME") != nullptr) - saveConnections = false; + saveExternalConnections = false; else if (std::getenv("NSM_URL") != nullptr) - saveConnections = false; + saveExternalConnections = false; else if (std::strcmp(getCurrentDriverName(), "Plugin") == 0) - saveConnections = false; + saveExternalConnections = false; } - if (saveConnections) + if (saveExternalConnections) { - if (const char* const* const patchbayConns = getPatchbayConnections()) + if (const char* const* const patchbayConns = getPatchbayConnections(true)) { MemoryOutputStream outPatchbay(2048); - outPatchbay << "\n \n"; + outPatchbay << "\n \n"; for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i ) { @@ -1694,7 +1721,7 @@ void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStream) const outPatchbay << " \n"; } - outPatchbay << " \n"; + outPatchbay << " \n"; outStream << outPatchbay; } } @@ -1896,7 +1923,46 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc) callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr); - // if we're running inside some session-manager, let them handle the connections + // handle connections (internal) + for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement()) + { + const String& tagName(elem->getTagName()); + + if (! tagName.equalsIgnoreCase("patchbay")) + continue; + + CarlaString sourcePort, targetPort; + + for (XmlElement* patchElem = elem->getFirstChildElement(); patchElem != nullptr; patchElem = patchElem->getNextElement()) + { + const String& patchTag(patchElem->getTagName()); + + sourcePort.clear(); + targetPort.clear(); + + if (! patchTag.equalsIgnoreCase("connection")) + continue; + + for (XmlElement* connElem = patchElem->getFirstChildElement(); connElem != nullptr; connElem = connElem->getNextElement()) + { + const String& tag(connElem->getTagName()); + const String text(connElem->getAllSubText().trim()); + + /**/ if (tag.equalsIgnoreCase("source")) + sourcePort = text.toRawUTF8(); + else if (tag.equalsIgnoreCase("target")) + targetPort = text.toRawUTF8(); + } + + if (sourcePort.isNotEmpty() && targetPort.isNotEmpty()) + restorePatchbayConnection(false, sourcePort, targetPort); + } + break; + } + + callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr); + + // if we're running inside some session-manager, let them handle the external connections if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY) { /**/ if (std::getenv("CARLA_DONT_MANAGE_CONNECTIONS") != nullptr) @@ -1909,12 +1975,12 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc) return true; } - // now handle connections + // handle connections (external) for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement()) { const String& tagName(elem->getTagName()); - if (! tagName.equalsIgnoreCase("patchbay")) + if (! tagName.equalsIgnoreCase("externalpatchbay")) continue; CarlaString sourcePort, targetPort; @@ -1941,10 +2007,11 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc) } if (sourcePort.isNotEmpty() && targetPort.isNotEmpty()) - restorePatchbayConnection(sourcePort, targetPort); + restorePatchbayConnection(true, sourcePort, targetPort); } break; } + #endif return true; diff --git a/source/backend/engine/CarlaEngineGraph.cpp b/source/backend/engine/CarlaEngineGraph.cpp index dd2b70145..7d1c97f28 100644 --- a/source/backend/engine/CarlaEngineGraph.cpp +++ b/source/backend/engine/CarlaEngineGraph.cpp @@ -1729,9 +1729,9 @@ void PatchbayGraph::refresh(const char* const deviceName) } } -const char* const* PatchbayGraph::getConnections() const +const char* const* PatchbayGraph::getConnections(const bool external) const { - if (connections.list.count() == 0) + if (connections.list.count() == 0 || external) return nullptr; CarlaStringList connList; @@ -2120,31 +2120,33 @@ bool CarlaEngine::patchbayRefresh(const bool external) // ----------------------------------------------------------------------- -const char* const* CarlaEngine::getPatchbayConnections() const +const char* const* CarlaEngine::getPatchbayConnections(const bool external) const { CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), nullptr); - carla_debug("CarlaEngine::getPatchbayConnections()"); + carla_debug("CarlaEngine::getPatchbayConnections(%s)", bool2str(external)); if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { + if (external) + return nullptr; if (RackGraph* const graph = pData->graph.getRackGraph()) return graph->getConnections(); } else { if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph()) - return graph->getConnections(); + return graph->getConnections(external); } return nullptr; } -void CarlaEngine::restorePatchbayConnection(const char* const sourcePort, const char* const targetPort) +void CarlaEngine::restorePatchbayConnection(const bool external, const char* const sourcePort, const char* const targetPort) { CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(),); CARLA_SAFE_ASSERT_RETURN(sourcePort != nullptr && sourcePort[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(targetPort != nullptr && targetPort[0] != '\0',); - carla_debug("CarlaEngine::restorePatchbayConnection(\"%s\", \"%s\")", sourcePort, targetPort); + carla_debug("CarlaEngine::restorePatchbayConnection(%s, \"%s\", \"%s\")", bool2str(external), sourcePort, targetPort); uint groupA, portA; uint groupB, portB; @@ -2154,6 +2156,8 @@ void CarlaEngine::restorePatchbayConnection(const char* const sourcePort, const RackGraph* const graph = pData->graph.getRackGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); + if (external) + return; if (! graph->getGroupAndPortIdFromFullName(sourcePort, groupA, portA)) return; if (! graph->getGroupAndPortIdFromFullName(targetPort, groupB, portB)) @@ -2164,6 +2168,7 @@ void CarlaEngine::restorePatchbayConnection(const char* const sourcePort, const PatchbayGraph* const graph = pData->graph.getPatchbayGraph(); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); + // TODO external if (! graph->getGroupAndPortIdFromFullName(sourcePort, groupA, portA)) return; if (! graph->getGroupAndPortIdFromFullName(targetPort, groupB, portB)) diff --git a/source/backend/engine/CarlaEngineGraph.hpp b/source/backend/engine/CarlaEngineGraph.hpp index 8bec240fa..bfb61b0f9 100644 --- a/source/backend/engine/CarlaEngineGraph.hpp +++ b/source/backend/engine/CarlaEngineGraph.hpp @@ -151,7 +151,7 @@ struct PatchbayGraph { void clearConnections(); void refresh(const char* const deviceName); - const char* const* getConnections() const; + const char* const* getConnections(const bool external) const; bool getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const; void process(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const int frames); diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index 3415ff7e7..a8fb416d6 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -1215,13 +1215,13 @@ public: // ------------------------------------------------------------------- // Patchbay stuff - const char* const* getPatchbayConnections() const override + const char* const* getPatchbayConnections(const bool external) const override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, nullptr); - carla_debug("CarlaEngineJack::getPatchbayConnections()"); + carla_debug("CarlaEngineJack::getPatchbayConnections(%s)", bool2str(external)); - if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) - return CarlaEngine::getPatchbayConnections(); + if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! external) + return CarlaEngine::getPatchbayConnections(external); CarlaStringList connList; @@ -1257,15 +1257,15 @@ public: return fRetConns; } - void restorePatchbayConnection(const char* const connSource, const char* const connTarget) override + void restorePatchbayConnection(const bool external, const char* const connSource, const char* const connTarget) override { CARLA_SAFE_ASSERT_RETURN(fClient != nullptr,); CARLA_SAFE_ASSERT_RETURN(connSource != nullptr && connSource[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(connTarget != nullptr && connTarget[0] != '\0',); carla_debug("CarlaEngineJack::restorePatchbayConnection(\"%s\", \"%s\")", connSource, connTarget); - if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) - return CarlaEngine::restorePatchbayConnection(connSource, connTarget); + if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! external) + return CarlaEngine::restorePatchbayConnection(external, connSource, connTarget); if (const jack_port_t* const port = jackbridge_port_by_name(fClient, connSource)) {