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 << " \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))
{