This is going to be needed for rtaudio/juce patchbay modes, but it's also nice to have for JACK.tags/1.9.6
@@ -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 | |||
// ------------------------------------------------------------------- | |||
@@ -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 <Patchbay>\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 << " <Connection>\n"; | |||
outPatchbay << " <Source>" << connSource << "</Source>\n"; | |||
outPatchbay << " <Target>" << connTarget << "</Target>\n"; | |||
outPatchbay << " </Connection>\n"; | |||
} | |||
outPatchbay << " </Patchbay>\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 <Patchbay>\n"; | |||
outPatchbay << "\n <ExternalPatchbay>\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 << " </Connection>\n"; | |||
} | |||
outPatchbay << " </Patchbay>\n"; | |||
outPatchbay << " </ExternalPatchbay>\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; | |||
@@ -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)) | |||
@@ -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); | |||
@@ -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)) | |||
{ | |||