Browse Source

Continue rework, now working properly I think...

tags/1.9.6
falkTX 10 years ago
parent
commit
5ac57536ef
8 changed files with 499 additions and 472 deletions
  1. +5
    -7
      source/backend/CarlaEngine.hpp
  2. +6
    -2
      source/backend/engine/CarlaEngine.cpp
  3. +298
    -250
      source/backend/engine/CarlaEngineGraph.cpp
  4. +29
    -24
      source/backend/engine/CarlaEngineGraph.hpp
  5. +1
    -0
      source/backend/engine/CarlaEngineInternal.hpp
  6. +2
    -3
      source/backend/engine/CarlaEngineJack.cpp
  7. +157
    -185
      source/backend/engine/CarlaEngineRtAudio.cpp
  8. +1
    -1
      source/modules/juce_audio_devices.h

+ 5
- 7
source/backend/CarlaEngine.hpp View File

@@ -1043,19 +1043,17 @@ public:
// Helper functions

/*!
* Return internal data, needed for EventPorts when used in Rack and Bridge modes.
* Return internal data, needed for EventPorts when used in Rack, Patchbay and Bridge modes.
* @note RT call
*/
EngineEvent* getInternalEventBuffer(const bool isInput) const noexcept;

#ifndef BUILD_BRIDGE
/*!
* Virtual functions for handling MIDI ports in the rack graph.
* Virtual functions for handling external graph ports.
*/
virtual bool connectRackMidiInPort(const char* const) { return false; }
virtual bool connectRackMidiOutPort(const char* const) { return false; }
virtual bool disconnectRackMidiInPort(const char* const) { return false; }
virtual bool disconnectRackMidiOutPort(const char* const) { return false; }
virtual bool connectExternalGraphPort(const uint, const uint, const char* const);
virtual bool disconnectExternalGraphPort(const uint, const uint, const char* const);
#endif

// -------------------------------------------------------------------
@@ -1122,7 +1120,7 @@ protected:
* Do not free returned data.
*/
virtual const char* const* getPatchbayConnections(const bool external) const;
virtual void restorePatchbayConnection(const bool external, const char* const sourcePort, const char* const targetPort);
virtual void restorePatchbayConnection(const bool external, const char* const sourcePort, const char* const targetPort, const bool sendCallback);
#endif

// -------------------------------------------------------------------


+ 6
- 2
source/backend/engine/CarlaEngine.cpp View File

@@ -1928,6 +1928,8 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
// handle connections (internal)
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
{
const bool isUsingExternal(pData->graph.isUsingExternal());

for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
{
const String& tagName(elem->getTagName());
@@ -1959,7 +1961,7 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
}

if (sourcePort.isNotEmpty() && targetPort.isNotEmpty())
restorePatchbayConnection(false, sourcePort, targetPort);
restorePatchbayConnection(false, sourcePort, targetPort, !isUsingExternal);
}
break;
}
@@ -1986,6 +1988,8 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
// handle connections (external)
if (loadExternalConnections)
{
const bool isUsingExternal(pData->graph.isUsingExternal());

for (XmlElement* elem = xmlElement->getFirstChildElement(); elem != nullptr; elem = elem->getNextElement())
{
const String& tagName(elem->getTagName());
@@ -2019,7 +2023,7 @@ bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc)
}

if (sourcePort.isNotEmpty() && targetPort.isNotEmpty())
restorePatchbayConnection(true, sourcePort, targetPort);
restorePatchbayConnection(true, sourcePort, targetPort, isUsingExternal);
}
break;
}


+ 298
- 250
source/backend/engine/CarlaEngineGraph.cpp View File

@@ -84,79 +84,6 @@ const char* getExternalGraphFullPortNameFromId(const /*RackGraphCarlaPortIds*/ u

// -----------------------------------------------------------------------

ExternalGraphBuffers::ExternalGraphBuffers() noexcept
: mutex(),
connectedIn1(),
connectedIn2(),
connectedOut1(),
connectedOut2()
#ifdef CARLA_PROPER_CPP11_SUPPORT
, inBuf{nullptr, nullptr},
inBufTmp{nullptr, nullptr},
outBuf{nullptr, nullptr} {}
#else
{
inBuf[0] = inBuf[1] = nullptr;
inBufTmp[0] = inBufTmp[1] = nullptr;
outBuf[0] = outBuf[1] = nullptr;
}
#endif

void ExternalGraphBuffers::setBufferSize(const uint32_t bufferSize, const bool createBuffers) noexcept
{
const int bufferSizei(static_cast<int>(bufferSize));

const CarlaRecursiveMutexLocker cml(mutex);

if (inBuf[0] != nullptr) { delete[] inBuf[0]; inBuf[0] = nullptr; }
if (inBuf[1] != nullptr) { delete[] inBuf[1]; inBuf[1] = nullptr; }
if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; }
if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; }
if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; }
if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; }

CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);

try {
inBufTmp[0] = new float[bufferSize];
inBufTmp[1] = new float[bufferSize];

if (createBuffers)
{
inBuf[0] = new float[bufferSize];
inBuf[1] = new float[bufferSize];
outBuf[0] = new float[bufferSize];
outBuf[1] = new float[bufferSize];
}
}
catch(...) {
if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; }
if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; }

if (createBuffers)
{
if (inBuf[0] != nullptr) { delete[] inBuf[0]; inBuf[0] = nullptr; }
if (inBuf[1] != nullptr) { delete[] inBuf[1]; inBuf[1] = nullptr; }
if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; }
if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; }
}
return;
}

FloatVectorOperations::clear(inBufTmp[0], bufferSizei);
FloatVectorOperations::clear(inBufTmp[1], bufferSizei);

if (createBuffers)
{
FloatVectorOperations::clear(inBuf[0], bufferSizei);
FloatVectorOperations::clear(inBuf[1], bufferSizei);
FloatVectorOperations::clear(outBuf[0], bufferSizei);
FloatVectorOperations::clear(outBuf[1], bufferSizei);
}
}

// -----------------------------------------------------------------------

ExternalGraphPorts::ExternalGraphPorts() noexcept
: ins(),
outs() {}
@@ -203,32 +130,21 @@ uint ExternalGraphPorts::getPortId(const bool isInput, const char portName[], bo

ExternalGraph::ExternalGraph(CarlaEngine* const engine) noexcept
: connections(),
audioBuffers(),
audioPorts(),
midiPorts(),
retCon(),
kEngine(engine) {}

void ExternalGraph::clearConnections() noexcept
void ExternalGraph::clear() noexcept
{
audioBuffers.mutex.lock();
audioBuffers.connectedIn1.clear();
audioBuffers.connectedIn2.clear();
audioBuffers.connectedOut1.clear();
audioBuffers.connectedOut2.clear();
audioBuffers.mutex.unlock();
connections.clear();
}

void ExternalGraph::clearPorts() noexcept
{
audioPorts.ins.clear();
audioPorts.outs.clear();
midiPorts.ins.clear();
midiPorts.outs.clear();
}

bool ExternalGraph::connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept
bool ExternalGraph::connect(const uint groupA, const uint portA, const uint groupB, const uint portB, const bool sendCallback) noexcept
{
uint otherGroup, otherPort, carlaPort;

@@ -258,42 +174,34 @@ bool ExternalGraph::connect(const uint groupA, const uint portA, const uint grou
{
case kExternalGraphCarlaPortAudioIn1:
CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupAudioIn, false);
audioBuffers.mutex.lock();
makeConnection = audioBuffers.connectedIn1.append(otherPort);
audioBuffers.mutex.unlock();
makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionAudioIn1, otherPort, nullptr);
break;

case kExternalGraphCarlaPortAudioIn2:
CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupAudioIn, false);
audioBuffers.mutex.lock();
makeConnection = audioBuffers.connectedIn2.append(otherPort);
audioBuffers.mutex.unlock();
makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionAudioIn2, otherPort, nullptr);
break;

case kExternalGraphCarlaPortAudioOut1:
CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupAudioOut, false);
audioBuffers.mutex.lock();
makeConnection = audioBuffers.connectedOut1.append(otherPort);
audioBuffers.mutex.unlock();
makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionAudioOut1, otherPort, nullptr);
break;

case kExternalGraphCarlaPortAudioOut2:
CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupAudioOut, false);
audioBuffers.mutex.lock();
makeConnection = audioBuffers.connectedOut2.append(otherPort);
audioBuffers.mutex.unlock();
makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionAudioOut2, otherPort, nullptr);
break;

case kExternalGraphCarlaPortMidiIn:
CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupMidiIn, false);
if (const char* const portName = midiPorts.getName(true, otherPort))
makeConnection = kEngine->connectRackMidiInPort(portName);
makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionMidiInput, 0, portName);
break;

case kExternalGraphCarlaPortMidiOut:
CARLA_SAFE_ASSERT_RETURN(otherGroup == kExternalGraphGroupMidiOut, false);
if (const char* const portName = midiPorts.getName(false, otherPort))
makeConnection = kEngine->connectRackMidiOutPort(portName);
makeConnection = kEngine->connectExternalGraphPort(kExternalGraphConnectionMidiOutput, 0, portName);
break;
}

@@ -310,7 +218,8 @@ bool ExternalGraph::connect(const uint groupA, const uint portA, const uint grou
strBuf[STR_MAX] = '\0';
std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);
if (sendCallback)
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

connections.list.append(connectionToId);
return true;
@@ -357,37 +266,29 @@ bool ExternalGraph::disconnect(const uint connectionId) noexcept
switch (carlaPort)
{
case kExternalGraphCarlaPortAudioIn1:
audioBuffers.mutex.lock();
makeDisconnection = audioBuffers.connectedIn1.removeOne(otherPort);
audioBuffers.mutex.unlock();
makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionAudioIn1, otherPort, nullptr);
break;

case kExternalGraphCarlaPortAudioIn2:
audioBuffers.mutex.lock();
makeDisconnection = audioBuffers.connectedIn2.removeOne(otherPort);
audioBuffers.mutex.unlock();
makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionAudioIn2, otherPort, nullptr);
break;

case kExternalGraphCarlaPortAudioOut1:
audioBuffers.mutex.lock();
makeDisconnection = audioBuffers.connectedOut1.removeOne(otherPort);
audioBuffers.mutex.unlock();
makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionAudioOut1, otherPort, nullptr);
break;

case kExternalGraphCarlaPortAudioOut2:
audioBuffers.mutex.lock();
makeDisconnection = audioBuffers.connectedOut2.removeOne(otherPort);
audioBuffers.mutex.unlock();
makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionAudioOut2, otherPort, nullptr);
break;

case kExternalGraphCarlaPortMidiIn:
if (const char* const portName = midiPorts.getName(true, otherPort))
makeDisconnection = kEngine->disconnectRackMidiInPort(portName);
makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionMidiInput, 0, portName);
break;

case kExternalGraphCarlaPortMidiOut:
if (const char* const portName = midiPorts.getName(false, otherPort))
makeDisconnection = kEngine->disconnectRackMidiOutPort(portName);
makeDisconnection = kEngine->disconnectExternalGraphPort(kExternalGraphConnectionMidiOutput, 0, portName);
break;
}

@@ -411,16 +312,20 @@ void ExternalGraph::refresh(const char* const deviceName)
{
CARLA_SAFE_ASSERT_RETURN(deviceName != nullptr,);

connections.clear();
const bool isRack(kEngine->getOptions().processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK);

// Main
{
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, kExternalGraphGroupCarla, PATCHBAY_ICON_CARLA, -1, 0.0f, kEngine->getName());

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2");
if (isRack)
{
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2");
}

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out");
}
@@ -429,6 +334,7 @@ void ExternalGraph::refresh(const char* const deviceName)
strBuf[STR_MAX] = '\0';

// Audio In
if (isRack)
{
if (deviceName[0] != '\0')
std::snprintf(strBuf, STR_MAX, "Capture (%s)", deviceName);
@@ -451,6 +357,7 @@ void ExternalGraph::refresh(const char* const deviceName)
}

// Audio Out
if (isRack)
{
if (deviceName[0] != '\0')
std::snprintf(strBuf, STR_MAX, "Playback (%s)", deviceName);
@@ -505,75 +412,6 @@ void ExternalGraph::refresh(const char* const deviceName)
PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, portNameToId.name);
}
}

// Connections
audioBuffers.mutex.lock();

for (LinkedList<uint>::Itenerator it = audioBuffers.connectedIn1.begin(); it.valid(); it.next())
{
const uint& portId(it.getValue(0));
CARLA_SAFE_ASSERT_CONTINUE(portId != 0);
CARLA_SAFE_ASSERT_CONTINUE(portId <= audioPorts.ins.count()); // FIXME <=

ConnectionToId connectionToId;
connectionToId.setData(++(connections.lastId), kExternalGraphGroupAudioIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn1);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

connections.list.append(connectionToId);
}

for (LinkedList<uint>::Itenerator it = audioBuffers.connectedIn2.begin(); it.valid(); it.next())
{
const uint& portId(it.getValue(0));
CARLA_SAFE_ASSERT_CONTINUE(portId != 0);
CARLA_SAFE_ASSERT_CONTINUE(portId <= audioPorts.ins.count()); // FIXME <=

ConnectionToId connectionToId;
connectionToId.setData(++(connections.lastId), kExternalGraphGroupAudioIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn2);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

connections.list.append(connectionToId);
}

for (LinkedList<uint>::Itenerator it = audioBuffers.connectedOut1.begin(); it.valid(); it.next())
{
const uint& portId(it.getValue(0));
CARLA_SAFE_ASSERT_CONTINUE(portId != 0);
CARLA_SAFE_ASSERT_CONTINUE(portId <= audioPorts.outs.count()); // FIXME <=

ConnectionToId connectionToId;
connectionToId.setData(++(connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut1, kExternalGraphGroupAudioOut, portId);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

connections.list.append(connectionToId);
}

for (LinkedList<uint>::Itenerator it = audioBuffers.connectedOut2.begin(); it.valid(); it.next())
{
const uint& portId(it.getValue(0));
CARLA_SAFE_ASSERT_CONTINUE(portId != 0);
CARLA_SAFE_ASSERT_CONTINUE(portId <= audioPorts.outs.count()); // FIXME <=

ConnectionToId connectionToId;
connectionToId.setData(++(connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut2, kExternalGraphGroupAudioOut, portId);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

connections.list.append(connectionToId);
}

audioBuffers.mutex.unlock();
}

const char* const* ExternalGraph::getConnections() const noexcept
@@ -656,6 +494,7 @@ const char* const* ExternalGraph::getConnections() const noexcept
bool ExternalGraph::getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const noexcept
{
CARLA_SAFE_ASSERT_RETURN(fullPortName != nullptr && fullPortName[0] != '\0', false);
carla_stdout("%s", fullPortName);

if (std::strncmp(fullPortName, "Carla:", 6) == 0)
{
@@ -695,6 +534,7 @@ bool ExternalGraph::getGroupAndPortIdFromFullName(const char* const fullPortName
{
bool ok;
portId = midiPorts.getPortId(true, portName, &ok);
carla_stdout("test %s %s", bool2str(ok), portName);
return ok;
}
}
@@ -713,6 +553,97 @@ bool ExternalGraph::getGroupAndPortIdFromFullName(const char* const fullPortName
return false;
}

// -----------------------------------------------------------------------
// RackGraph Buffers

RackGraph::Buffers::Buffers() noexcept
: mutex(),
connectedIn1(),
connectedIn2(),
connectedOut1(),
connectedOut2()
#ifdef CARLA_PROPER_CPP11_SUPPORT
, inBuf{nullptr, nullptr},
inBufTmp{nullptr, nullptr},
outBuf{nullptr, nullptr} {}
#else
{
inBuf[0] = inBuf[1] = nullptr;
inBufTmp[0] = inBufTmp[1] = nullptr;
outBuf[0] = outBuf[1] = nullptr;
}
#endif

RackGraph::Buffers::~Buffers() noexcept
{
const CarlaRecursiveMutexLocker cml(mutex);

if (inBuf[0] != nullptr) { delete[] inBuf[0]; inBuf[0] = nullptr; }
if (inBuf[1] != nullptr) { delete[] inBuf[1]; inBuf[1] = nullptr; }
if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; }
if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; }
if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; }
if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; }

connectedIn1.clear();
connectedIn2.clear();
connectedOut1.clear();
connectedOut2.clear();
}

void RackGraph::Buffers::setBufferSize(const uint32_t bufferSize, const bool createBuffers) noexcept
{
const int bufferSizei(static_cast<int>(bufferSize));

const CarlaRecursiveMutexLocker cml(mutex);

if (inBuf[0] != nullptr) { delete[] inBuf[0]; inBuf[0] = nullptr; }
if (inBuf[1] != nullptr) { delete[] inBuf[1]; inBuf[1] = nullptr; }
if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; }
if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; }
if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; }
if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; }

CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);

try {
inBufTmp[0] = new float[bufferSize];
inBufTmp[1] = new float[bufferSize];

if (createBuffers)
{
inBuf[0] = new float[bufferSize];
inBuf[1] = new float[bufferSize];
outBuf[0] = new float[bufferSize];
outBuf[1] = new float[bufferSize];
}
}
catch(...) {
if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; }
if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; }

if (createBuffers)
{
if (inBuf[0] != nullptr) { delete[] inBuf[0]; inBuf[0] = nullptr; }
if (inBuf[1] != nullptr) { delete[] inBuf[1]; inBuf[1] = nullptr; }
if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; }
if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; }
}
return;
}

FloatVectorOperations::clear(inBufTmp[0], bufferSizei);
FloatVectorOperations::clear(inBufTmp[1], bufferSizei);

if (createBuffers)
{
FloatVectorOperations::clear(inBuf[0], bufferSizei);
FloatVectorOperations::clear(inBuf[1], bufferSizei);
FloatVectorOperations::clear(outBuf[0], bufferSizei);
FloatVectorOperations::clear(outBuf[1], bufferSizei);
}
}

// -----------------------------------------------------------------------
// RackGraph

@@ -721,6 +652,7 @@ RackGraph::RackGraph(CarlaEngine* const engine, const uint32_t ins, const uint32
inputs(ins),
outputs(outs),
isOffline(false),
audioBuffers(),
kEngine(engine)
{
setBufferSize(engine->getBufferSize());
@@ -728,13 +660,12 @@ RackGraph::RackGraph(CarlaEngine* const engine, const uint32_t ins, const uint32

RackGraph::~RackGraph() noexcept
{
extGraph.clearConnections();
extGraph.clearPorts();
extGraph.clear();
}

void RackGraph::setBufferSize(const uint32_t bufferSize) noexcept
{
extGraph.audioBuffers.setBufferSize(bufferSize, (inputs > 0 || outputs > 0));
audioBuffers.setBufferSize(bufferSize, (inputs > 0 || outputs > 0));
}

void RackGraph::setOffline(const bool offline) noexcept
@@ -744,7 +675,7 @@ void RackGraph::setOffline(const bool offline) noexcept

bool RackGraph::connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept
{
return extGraph.connect(groupA, portA, groupB, portB);
return extGraph.connect(groupA, portA, groupB, portB, true);
}

bool RackGraph::disconnect(const uint connectionId) noexcept
@@ -752,19 +683,79 @@ bool RackGraph::disconnect(const uint connectionId) noexcept
return extGraph.disconnect(connectionId);
}

void RackGraph::clearPorts() noexcept
{
extGraph.clearPorts();
}

void RackGraph::clearConnections() noexcept
{
extGraph.clearConnections();
}

void RackGraph::refresh(const char* const deviceName)
{
extGraph.refresh(deviceName);

char strBuf[STR_MAX+1];
strBuf[STR_MAX] = '\0';

// Connections
const CarlaRecursiveMutexLocker cml(audioBuffers.mutex);

for (LinkedList<uint>::Itenerator it = audioBuffers.connectedIn1.begin(); it.valid(); it.next())
{
const uint& portId(it.getValue(0));
CARLA_SAFE_ASSERT_CONTINUE(portId != 0);
CARLA_SAFE_ASSERT_CONTINUE(portId <= extGraph.audioPorts.ins.count()); // FIXME <=

ConnectionToId connectionToId;
connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupAudioIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn1);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

extGraph.connections.list.append(connectionToId);
}

for (LinkedList<uint>::Itenerator it = audioBuffers.connectedIn2.begin(); it.valid(); it.next())
{
const uint& portId(it.getValue(0));
CARLA_SAFE_ASSERT_CONTINUE(portId != 0);
CARLA_SAFE_ASSERT_CONTINUE(portId <= extGraph.audioPorts.ins.count()); // FIXME <=

ConnectionToId connectionToId;
connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupAudioIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioIn2);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

extGraph.connections.list.append(connectionToId);
}

for (LinkedList<uint>::Itenerator it = audioBuffers.connectedOut1.begin(); it.valid(); it.next())
{
const uint& portId(it.getValue(0));
CARLA_SAFE_ASSERT_CONTINUE(portId != 0);
CARLA_SAFE_ASSERT_CONTINUE(portId <= extGraph.audioPorts.outs.count()); // FIXME <=

ConnectionToId connectionToId;
connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut1, kExternalGraphGroupAudioOut, portId);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

extGraph.connections.list.append(connectionToId);
}

for (LinkedList<uint>::Itenerator it = audioBuffers.connectedOut2.begin(); it.valid(); it.next())
{
const uint& portId(it.getValue(0));
CARLA_SAFE_ASSERT_CONTINUE(portId != 0);
CARLA_SAFE_ASSERT_CONTINUE(portId <= extGraph.audioPorts.outs.count()); // FIXME <=

ConnectionToId connectionToId;
connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortAudioOut2, kExternalGraphGroupAudioOut, portId);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

extGraph.connections.list.append(connectionToId);
}
}

const char* const* RackGraph::getConnections() const noexcept
@@ -899,9 +890,6 @@ void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inB

void RackGraph::processHelper(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames)
{
// FIXME
ExternalGraphBuffers& audioBuffers(extGraph.audioBuffers);

CARLA_SAFE_ASSERT_RETURN(audioBuffers.outBuf[1] != nullptr,);

const int iframes(static_cast<int>(frames));
@@ -1363,20 +1351,17 @@ PatchbayGraph::PatchbayGraph(CarlaEngine* const engine, const uint32_t ins, cons
extGraph(engine),
kEngine(engine)
{
const uint32_t bufferSize(engine->getBufferSize());
const int bufferSizei(static_cast<int>(bufferSize));
const double sampleRate(engine->getSampleRate());
const int bufferSize(static_cast<int>(engine->getBufferSize()));
const double sampleRate(engine->getSampleRate());

graph.setPlayConfigDetails(static_cast<int>(inputs), static_cast<int>(outputs), sampleRate, bufferSizei);
graph.prepareToPlay(sampleRate, bufferSizei);
graph.setPlayConfigDetails(static_cast<int>(inputs), static_cast<int>(outputs), sampleRate, bufferSize);
graph.prepareToPlay(sampleRate, bufferSize);

audioBuffer.setSize(static_cast<int>(jmax(inputs, outputs)), bufferSizei);
audioBuffer.setSize(static_cast<int>(jmax(inputs, outputs)), bufferSize);

midiBuffer.ensureSize(kMaxEngineEventInternalCount*2);
midiBuffer.clear();

extGraph.audioBuffers.setBufferSize(bufferSize, (inputs > 0 || outputs > 0));

{
AudioProcessorGraph::AudioGraphIOProcessor* const proc(new AudioProcessorGraph::AudioGraphIOProcessor(AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode));
AudioProcessorGraph::Node* const node(graph.addNode(proc));
@@ -1424,9 +1409,8 @@ PatchbayGraph::PatchbayGraph(CarlaEngine* const engine, const uint32_t ins, cons

PatchbayGraph::~PatchbayGraph()
{
clearInternalConnections();
extGraph.clearConnections();
extGraph.clearPorts();
connections.clear();
extGraph.clear();

graph.releaseResources();
graph.clear();
@@ -1440,8 +1424,6 @@ void PatchbayGraph::setBufferSize(const uint32_t bufferSize)
graph.releaseResources();
graph.prepareToPlay(kEngine->getSampleRate(), bufferSizei);
audioBuffer.setSize(audioBuffer.getNumChannels(), bufferSizei);

extGraph.audioBuffers.setBufferSize(bufferSize, (inputs > 0 || outputs > 0));
}

void PatchbayGraph::setSampleRate(const double sampleRate)
@@ -1485,7 +1467,7 @@ void PatchbayGraph::replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* con

if (! usingExternal)
{
disconnectGroup(oldNode->nodeId);
disconnectInternalGroup(oldNode->nodeId);
removeNodeFromPatchbay(kEngine, oldNode->nodeId, oldNode->getProcessor());
}

@@ -1516,7 +1498,7 @@ void PatchbayGraph::removePlugin(CarlaPlugin* const plugin)

if (! usingExternal)
{
disconnectGroup(node->nodeId);
disconnectInternalGroup(node->nodeId);
removeNodeFromPatchbay(kEngine, node->nodeId, node->getProcessor());
}

@@ -1552,7 +1534,7 @@ void PatchbayGraph::removeAllPlugins()

if (! usingExternal)
{
disconnectGroup(node->nodeId);
disconnectInternalGroup(node->nodeId);
removeNodeFromPatchbay(kEngine, node->nodeId, node->getProcessor());
}

@@ -1562,10 +1544,10 @@ void PatchbayGraph::removeAllPlugins()
}
}

bool PatchbayGraph::connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept
bool PatchbayGraph::connect(const bool external, const uint groupA, const uint portA, const uint groupB, const uint portB, const bool sendCallback)
{
if (usingExternal)
return extGraph.connect(groupA, portA, groupB, portB);
if (external)
return extGraph.connect(groupA, portA, groupB, portB, sendCallback);

uint adjustedPortA = portA;
uint adjustedPortB = portB;
@@ -1588,13 +1570,14 @@ bool PatchbayGraph::connect(const uint groupA, const uint portA, const uint grou
strBuf[STR_MAX] = '\0';
std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB);

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);
if (sendCallback)
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);

connections.list.append(connectionToId);
return true;
}

bool PatchbayGraph::disconnect(const uint connectionId) noexcept
bool PatchbayGraph::disconnect(const uint connectionId)
{
if (usingExternal)
return extGraph.disconnect(connectionId);
@@ -1631,7 +1614,7 @@ bool PatchbayGraph::disconnect(const uint connectionId) noexcept
return false;
}

void PatchbayGraph::disconnectGroup(const uint groupId) noexcept
void PatchbayGraph::disconnectInternalGroup(const uint groupId) noexcept
{
CARLA_SAFE_ASSERT(! usingExternal);

@@ -1658,20 +1641,13 @@ void PatchbayGraph::disconnectGroup(const uint groupId) noexcept
connectionToId.groupB, static_cast<int>(adjustedPortB));
*/

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0.0f, nullptr);
if (! usingExternal)
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0.0f, nullptr);

connections.list.remove(it);
}
}

void PatchbayGraph::clearInternalConnections()
{
connections.clear();

for (int i=0, count=graph.getNumConnections(); i<count; ++i)
graph.removeConnection(0);
}

void PatchbayGraph::refresh(const char* const deviceName)
{
if (usingExternal)
@@ -2053,6 +2029,15 @@ void EngineInternalGraph::removeAllPlugins()
fPatchbay->removeAllPlugins();
}

bool EngineInternalGraph::isUsingExternal() const noexcept
{
if (fIsRack)
return true;

CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr, false);
return fPatchbay->usingExternal;
}

void EngineInternalGraph::setUsingExternal(const bool usingExternal) noexcept
{
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
@@ -2070,13 +2055,17 @@ bool CarlaEngine::patchbayConnect(const uint groupA, const uint portA, const uin

if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
if (RackGraph* const graph = pData->graph.getRackGraph())
return graph->connect(groupA, portA, groupB, portB);
RackGraph* const graph = pData->graph.getRackGraph();
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);

return graph->connect(groupA, portA, groupB, portB);
}
else
{
if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph())
return graph->connect(groupA, portA, groupB, portB);
PatchbayGraph* const graph = pData->graph.getPatchbayGraph();
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);

return graph->connect(graph->usingExternal, groupA, portA, groupB, portB, true);
}

return false;
@@ -2090,13 +2079,17 @@ bool CarlaEngine::patchbayDisconnect(const uint connectionId)

if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
if (RackGraph* const graph = pData->graph.getRackGraph())
return graph->disconnect(connectionId);
RackGraph* const graph = pData->graph.getRackGraph();
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);

return graph->disconnect(connectionId);
}
else
{
if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph())
return graph->disconnect(connectionId);
PatchbayGraph* const graph = pData->graph.getPatchbayGraph();
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);

return graph->disconnect(connectionId);
}

return false;
@@ -2116,9 +2109,10 @@ bool CarlaEngine::patchbayRefresh(const bool external)

if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
{
if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph())
graph->refresh("");
PatchbayGraph* const graph = pData->graph.getPatchbayGraph();
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);

graph->refresh("");
return true;
}

@@ -2152,12 +2146,12 @@ const char* const* CarlaEngine::getPatchbayConnections(const bool external) cons
return nullptr;
}

void CarlaEngine::restorePatchbayConnection(const bool external, const char* const sourcePort, const char* const targetPort)
void CarlaEngine::restorePatchbayConnection(const bool external, const char* const sourcePort, const char* const targetPort, const bool sendCallback)
{
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\", \"%s\")", bool2str(external), sourcePort, targetPort);
carla_stdout("CarlaEngine::restorePatchbayConnection(%s, \"%s\", \"%s\")", bool2str(external), sourcePort, targetPort);

uint groupA, portA;
uint groupB, portB;
@@ -2172,6 +2166,8 @@ void CarlaEngine::restorePatchbayConnection(const bool external, const char* con
return;
if (! graph->getGroupAndPortIdFromFullName(targetPort, groupB, portB))
return;

graph->connect(groupA, portA, groupB, portB);
}
else
{
@@ -2182,9 +2178,61 @@ void CarlaEngine::restorePatchbayConnection(const bool external, const char* con
return;
if (! graph->getGroupAndPortIdFromFullName(external, targetPort, groupB, portB))
return;

graph->connect(external, groupA, portA, groupB, portB, sendCallback);
}
}

// -----------------------------------------------------------------------

bool CarlaEngine::connectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName)
{
CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false);
CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK, false);

RackGraph* const graph(pData->graph.getRackGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);

patchbayConnect(groupA, portA, groupB, portB);
const CarlaRecursiveMutexLocker cml(graph->audioBuffers.mutex);

switch (connectionType)
{
case kExternalGraphConnectionAudioIn1:
return graph->audioBuffers.connectedIn1.append(portId);
case kExternalGraphConnectionAudioIn2:
return graph->audioBuffers.connectedIn2.append(portId);
case kExternalGraphConnectionAudioOut1:
return graph->audioBuffers.connectedOut1.append(portId);
case kExternalGraphConnectionAudioOut2:
return graph->audioBuffers.connectedOut2.append(portId);
}

return false;
}

bool CarlaEngine::disconnectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName)
{
CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false);
CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK, false);

RackGraph* const graph(pData->graph.getRackGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);

const CarlaRecursiveMutexLocker cml(graph->audioBuffers.mutex);

switch (connectionType)
{
case kExternalGraphConnectionAudioIn1:
return graph->audioBuffers.connectedIn1.removeOne(portId);
case kExternalGraphConnectionAudioIn2:
return graph->audioBuffers.connectedIn2.removeOne(portId);
case kExternalGraphConnectionAudioOut1:
return graph->audioBuffers.connectedOut1.removeOne(portId);
case kExternalGraphConnectionAudioOut2:
return graph->audioBuffers.connectedOut2.removeOne(portId);
}

return false;
}

// -----------------------------------------------------------------------


+ 29
- 24
source/backend/engine/CarlaEngineGraph.hpp View File

@@ -54,19 +54,14 @@ enum ExternalGraphCarlaPortIds {
kExternalGraphCarlaPortMax = 7
};

struct ExternalGraphBuffers {
CarlaRecursiveMutex mutex;
LinkedList<uint> connectedIn1;
LinkedList<uint> connectedIn2;
LinkedList<uint> connectedOut1;
LinkedList<uint> connectedOut2;
float* inBuf[2];
float* inBufTmp[2];
float* outBuf[2];
ExternalGraphBuffers() noexcept;
void setBufferSize(const uint32_t bufferSize, const bool createBuffers) noexcept;
CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(ExternalGraphBuffers)
enum ExternalGraphConnectionType {
kExternalGraphConnectionNull = 0,
kExternalGraphConnectionAudioIn1 = 1,
kExternalGraphConnectionAudioIn2 = 2,
kExternalGraphConnectionAudioOut1 = 3,
kExternalGraphConnectionAudioOut2 = 4,
kExternalGraphConnectionMidiInput = 5,
kExternalGraphConnectionMidiOutput = 6
};

struct ExternalGraphPorts {
@@ -81,15 +76,12 @@ struct ExternalGraphPorts {

struct ExternalGraph {
PatchbayConnectionList connections;
ExternalGraphBuffers audioBuffers;
ExternalGraphPorts audioPorts, midiPorts;
mutable CharStringListPtr retCon;
ExternalGraph(CarlaEngine* const engine) noexcept;

void clearConnections() noexcept;
void clearPorts() noexcept;

bool connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept;
void clear() noexcept;
bool connect(const uint groupA, const uint portA, const uint groupB, const uint portB, const bool sendCallback) noexcept;
bool disconnect(const uint connectionId) noexcept;
void refresh(const char* const deviceName);

@@ -110,6 +102,22 @@ struct RackGraph {
const uint32_t outputs;
bool isOffline;

struct Buffers {
CarlaRecursiveMutex mutex;
LinkedList<uint> connectedIn1;
LinkedList<uint> connectedIn2;
LinkedList<uint> connectedOut1;
LinkedList<uint> connectedOut2;
float* inBuf[2];
float* inBufTmp[2];
float* outBuf[2];
Buffers() noexcept;
~Buffers() noexcept;
void setBufferSize(const uint32_t bufferSize, const bool createBuffers) noexcept;
CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(Buffers)
} audioBuffers;

RackGraph(CarlaEngine* const engine, const uint32_t inputs, const uint32_t outputs) noexcept;
~RackGraph() noexcept;

@@ -118,8 +126,6 @@ struct RackGraph {

bool connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept;
bool disconnect(const uint connectionId) noexcept;
void clearPorts() noexcept;
void clearConnections() noexcept;
void refresh(const char* const deviceName);

const char* const* getConnections() const noexcept;
@@ -162,10 +168,9 @@ struct PatchbayGraph {
void removePlugin(CarlaPlugin* const plugin);
void removeAllPlugins();

bool connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept;
bool disconnect(const uint connectionId) noexcept;
void disconnectGroup(const uint groupId) noexcept;
void clearInternalConnections();
bool connect(const bool external, const uint groupA, const uint portA, const uint groupB, const uint portB, const bool sendCallback);
bool disconnect(const uint connectionId);
void disconnectInternalGroup(const uint groupId) noexcept;
void refresh(const char* const deviceName);

const char* const* getConnections(const bool external) const;


+ 1
- 0
source/backend/engine/CarlaEngineInternal.hpp View File

@@ -86,6 +86,7 @@ public:
void removePlugin(CarlaPlugin* const plugin);
void removeAllPlugins();

bool isUsingExternal() const noexcept;
void setUsingExternal(const bool usingExternal) noexcept;

private:


+ 2
- 3
source/backend/engine/CarlaEngineJack.cpp View File

@@ -817,7 +817,6 @@ public:
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
pData->graph.create(0, 0);
patchbayRefresh(true);
}
else
{
@@ -1258,7 +1257,7 @@ public:
return fRetConns;
}

void restorePatchbayConnection(const bool external, const char* const connSource, const char* const connTarget) override
void restorePatchbayConnection(const bool external, const char* const connSource, const char* const connTarget, const bool sendCallback) override
{
CARLA_SAFE_ASSERT_RETURN(fClient != nullptr,);
CARLA_SAFE_ASSERT_RETURN(connSource != nullptr && connSource[0] != '\0',);
@@ -1266,7 +1265,7 @@ public:
carla_debug("CarlaEngineJack::restorePatchbayConnection(\"%s\", \"%s\")", connSource, connTarget);

if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! external)
return CarlaEngine::restorePatchbayConnection(external, connSource, connTarget);
return CarlaEngine::restorePatchbayConnection(external, connSource, connTarget, sendCallback);

if (const jack_port_t* const port = jackbridge_port_by_name(fClient, connSource))
{


+ 157
- 185
source/backend/engine/CarlaEngineRtAudio.cpp View File

@@ -307,6 +307,9 @@ public:

patchbayRefresh(false);

if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
refreshExternalGraphPorts<PatchbayGraph>(pData->graph.getPatchbayGraph(), false);

callback(ENGINE_CALLBACK_ENGINE_STARTED, 0, pData->options.processMode, pData->options.transportMode, 0.0f, getCurrentDriverName());
return true;
}
@@ -403,15 +406,19 @@ public:
// Patchbay

template<class Graph>
bool refreshGraphPorts(Graph& graph)
bool refreshExternalGraphPorts(Graph* const graph, const bool sendCallback)
{
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);

char strBuf[STR_MAX+1];
strBuf[STR_MAX] = '\0';

ExternalGraph& extGraph(graph->extGraph);

// ---------------------------------------------------------------
// clear last ports

graph.clearPorts();
extGraph.clear();

// ---------------------------------------------------------------
// fill in new ones
@@ -424,7 +431,7 @@ public:
PortNameToId portNameToId;
portNameToId.setData(kExternalGraphGroupAudioIn, i+1, strBuf, "");

graph.audioPorts.ins.append(portNameToId);
extGraph.audioPorts.ins.append(portNameToId);
}

// Audio Out
@@ -435,7 +442,7 @@ public:
PortNameToId portNameToId;
portNameToId.setData(kExternalGraphGroupAudioOut, i+1, strBuf, "");

graph.audioPorts.outs.append(portNameToId);
extGraph.audioPorts.outs.append(portNameToId);
}

// MIDI In
@@ -447,7 +454,7 @@ public:
PortNameToId portNameToId;
portNameToId.setData(kExternalGraphGroupMidiIn, i+1, midiIn.getPortName(i).c_str(), "");

graph.midiPorts.ins.append(portNameToId);
extGraph.midiPorts.ins.append(portNameToId);
}
}

@@ -460,14 +467,15 @@ public:
PortNameToId portNameToId;
portNameToId.setData(kExternalGraphGroupMidiOut, i+1, midiOut.getPortName(i).c_str(), "");

graph.midiPorts.outs.append(portNameToId);
extGraph.midiPorts.outs.append(portNameToId);
}
}

// ---------------------------------------------------------------
// now refresh

graph.refresh(fDeviceName.buffer());
if (sendCallback)
graph->refresh(fDeviceName.buffer());

// ---------------------------------------------------------------
// add midi connections
@@ -479,17 +487,18 @@ public:
const MidiInPort& inPort(it.getValue(fallback));
CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr);

const uint portId(graph.midiPorts.getPortId(true, inPort.name));
CARLA_SAFE_ASSERT_CONTINUE(portId < graph.midiPorts.ins.count());
const uint portId(extGraph.midiPorts.getPortId(true, inPort.name));
CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.ins.count());

ConnectionToId connectionToId;
connectionToId.setData(++(graph.connections.lastId), kExternalGraphGroupMidiIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn);
connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupMidiIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);
extGraph.connections.list.append(connectionToId);

graph.connections.list.append(connectionToId);
if (sendCallback)
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);
}

fMidiOutMutex.lock();
@@ -501,17 +510,18 @@ public:
const MidiOutPort& outPort(it.getValue(fallback));
CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr);

const uint portId(graph.midiPorts.getPortId(false, outPort.name));
CARLA_SAFE_ASSERT_CONTINUE(portId < graph.midiPorts.outs.count());
const uint portId(extGraph.midiPorts.getPortId(false, outPort.name));
CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.outs.count());

ConnectionToId connectionToId;
connectionToId.setData(++(graph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, kExternalGraphGroupMidiOut, portId);
connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, kExternalGraphGroupMidiOut, portId);

std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);

callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);
extGraph.connections.list.append(connectionToId);

graph.connections.list.append(connectionToId);
if (sendCallback)
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf);
}

fMidiOutMutex.unlock();
@@ -525,16 +535,16 @@ public:

if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
return refreshGraphPorts<ExternalGraph>(pData->graph.getRackGraph()->extGraph);
return refreshExternalGraphPorts<RackGraph>(pData->graph.getRackGraph(), true);
}
else
{
pData->graph.setUsingExternal(external);

if (! external)
if (external)
return refreshExternalGraphPorts<PatchbayGraph>(pData->graph.getPatchbayGraph(), true);
else
return CarlaEngine::patchbayRefresh(false);

return refreshGraphPorts<ExternalGraph>(pData->graph.getPatchbayGraph()->extGraph);
}

return true;
@@ -734,208 +744,170 @@ protected:

// -------------------------------------------------------------------

bool connectRackMidiInPort(const char* const portName) override
bool connectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) override
{
CARLA_SAFE_ASSERT_RETURN(portName != nullptr && portName[0] != '\0', false);
carla_debug("CarlaEngineRtAudio::connectRackMidiInPort(\"%s\")", portName);

if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
RackGraph* const graph(pData->graph.getRackGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.ins.count() > 0, false);
}
else
{
PatchbayGraph* const graph(pData->graph.getPatchbayGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.ins.count() > 0, false);
}

CarlaString newRtMidiPortName;
newRtMidiPortName += getName();
newRtMidiPortName += ":";
newRtMidiPortName += portName;

RtMidiIn* const rtMidiIn(new RtMidiIn(getMatchedAudioMidiAPI(fAudio.getCurrentApi()), newRtMidiPortName.buffer(), 512));
rtMidiIn->ignoreTypes();
rtMidiIn->setCallback(carla_rtmidi_callback, this);
CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false);
carla_stdout("CarlaEngineRtAudio::connectExternalGraphPort(%u, %u, \"%s\")", connectionType, portId, portName);

bool found = false;
uint rtMidiPortIndex;

for (uint i=0, count=rtMidiIn->getPortCount(); i < count; ++i)
switch (connectionType)
{
if (rtMidiIn->getPortName(i) == portName)
case kExternalGraphConnectionAudioIn1:
case kExternalGraphConnectionAudioIn2:
case kExternalGraphConnectionAudioOut1:
case kExternalGraphConnectionAudioOut2:
return CarlaEngine::connectExternalGraphPort(connectionType, portId, portName);

case kExternalGraphConnectionMidiInput: {
CarlaString newRtMidiPortName;
newRtMidiPortName += getName();
newRtMidiPortName += ":";
newRtMidiPortName += portName;

RtMidiIn* const rtMidiIn(new RtMidiIn(getMatchedAudioMidiAPI(fAudio.getCurrentApi()), newRtMidiPortName.buffer(), 512));
rtMidiIn->ignoreTypes();
rtMidiIn->setCallback(carla_rtmidi_callback, this);

bool found = false;
uint rtMidiPortIndex;

for (uint i=0, count=rtMidiIn->getPortCount(); i < count; ++i)
{
found = true;
rtMidiPortIndex = i;
break;
if (rtMidiIn->getPortName(i) == portName)
{
found = true;
rtMidiPortIndex = i;
break;
}
}
}

if (! found)
{
delete rtMidiIn;
return false;
}

try {
rtMidiIn->openPort(rtMidiPortIndex, portName);
}
catch(...) {
delete rtMidiIn;
return false;
};
if (! found)
{
delete rtMidiIn;
return false;
}

MidiInPort midiPort;
midiPort.port = rtMidiIn;
try {
rtMidiIn->openPort(rtMidiPortIndex, portName);
}
catch(...) {
delete rtMidiIn;
return false;
};

std::strncpy(midiPort.name, portName, STR_MAX);
midiPort.name[STR_MAX] = '\0';
MidiInPort midiPort;
midiPort.port = rtMidiIn;

fMidiIns.append(midiPort);
return true;
}
std::strncpy(midiPort.name, portName, STR_MAX);
midiPort.name[STR_MAX] = '\0';

bool connectRackMidiOutPort(const char* const portName) override
{
CARLA_SAFE_ASSERT_RETURN(portName != nullptr && portName[0] != '\0', false);
carla_debug("CarlaEngineRtAudio::connectRackMidiOutPort(\"%s\")", portName);
fMidiIns.append(midiPort);
return true;
} break;

if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
RackGraph* const graph(pData->graph.getRackGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.outs.count() > 0, false);
}
else
{
PatchbayGraph* const graph(pData->graph.getPatchbayGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.outs.count() > 0, false);
}
case kExternalGraphConnectionMidiOutput: {
CarlaString newRtMidiPortName;
newRtMidiPortName += getName();
newRtMidiPortName += ":";
newRtMidiPortName += portName;

CarlaString newRtMidiPortName;
newRtMidiPortName += getName();
newRtMidiPortName += ":";
newRtMidiPortName += portName;
RtMidiOut* const rtMidiOut(new RtMidiOut(getMatchedAudioMidiAPI(fAudio.getCurrentApi()), newRtMidiPortName.buffer()));

RtMidiOut* const rtMidiOut(new RtMidiOut(getMatchedAudioMidiAPI(fAudio.getCurrentApi()), newRtMidiPortName.buffer()));
bool found = false;
uint rtMidiPortIndex;

bool found = false;
uint rtMidiPortIndex;
for (uint i=0, count=rtMidiOut->getPortCount(); i < count; ++i)
{
if (rtMidiOut->getPortName(i) == portName)
{
found = true;
rtMidiPortIndex = i;
break;
}
}

for (uint i=0, count=rtMidiOut->getPortCount(); i < count; ++i)
{
if (rtMidiOut->getPortName(i) == portName)
if (! found)
{
found = true;
rtMidiPortIndex = i;
break;
delete rtMidiOut;
return false;
}
}

if (! found)
{
delete rtMidiOut;
return false;
}
try {
rtMidiOut->openPort(rtMidiPortIndex, portName);
}
catch(...) {
delete rtMidiOut;
return false;
};

try {
rtMidiOut->openPort(rtMidiPortIndex, portName);
}
catch(...) {
delete rtMidiOut;
return false;
};
MidiOutPort midiPort;
midiPort.port = rtMidiOut;

MidiOutPort midiPort;
midiPort.port = rtMidiOut;
std::strncpy(midiPort.name, portName, STR_MAX);
midiPort.name[STR_MAX] = '\0';

std::strncpy(midiPort.name, portName, STR_MAX);
midiPort.name[STR_MAX] = '\0';
const CarlaMutexLocker cml(fMidiOutMutex);

const CarlaMutexLocker cml(fMidiOutMutex);
fMidiOuts.append(midiPort);
return true;
} break;
}

fMidiOuts.append(midiPort);
return true;
return false;
}

bool disconnectRackMidiInPort(const char* const portName) override
bool disconnectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) override
{
CARLA_SAFE_ASSERT_RETURN(portName != nullptr && portName[0] != '\0', false);
carla_debug("CarlaEngineRtAudio::disconnectRackMidiInPort(\"%s\")", portName);
CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false);
carla_debug("CarlaEngineRtAudio::disconnectExternalGraphPort(%u, %u, \"%s\")", connectionType, portId, portName);

if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
RackGraph* const graph(pData->graph.getRackGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.ins.count() > 0, false);
}
else
switch (connectionType)
{
PatchbayGraph* const graph(pData->graph.getPatchbayGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.ins.count() > 0, false);
}

for (LinkedList<MidiInPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next())
{
static MidiInPort fallback = { nullptr, { '\0' } };

MidiInPort& inPort(it.getValue(fallback));
CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr);

if (std::strncmp(inPort.name, portName, STR_MAX) != 0)
continue;

inPort.port->cancelCallback();
inPort.port->closePort();
delete inPort.port;
case kExternalGraphConnectionAudioIn1:
case kExternalGraphConnectionAudioIn2:
case kExternalGraphConnectionAudioOut1:
case kExternalGraphConnectionAudioOut2:
return CarlaEngine::disconnectExternalGraphPort(connectionType, portId, portName);

case kExternalGraphConnectionMidiInput:
for (LinkedList<MidiInPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next())
{
static MidiInPort fallback = { nullptr, { '\0' } };

fMidiIns.remove(it);
return true;
}
MidiInPort& inPort(it.getValue(fallback));
CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr);

return false;
}
if (std::strncmp(inPort.name, portName, STR_MAX) != 0)
continue;

bool disconnectRackMidiOutPort(const char* const portName) override
{
CARLA_SAFE_ASSERT_RETURN(portName != nullptr && portName[0] != '\0', false);
carla_debug("CarlaEngineRtAudio::disconnectRackMidiOutPort(\"%s\")", portName);
inPort.port->cancelCallback();
inPort.port->closePort();
delete inPort.port;

if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
RackGraph* const graph(pData->graph.getRackGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.outs.count() > 0, false);
}
else
{
PatchbayGraph* const graph(pData->graph.getPatchbayGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.outs.count() > 0, false);
}
fMidiIns.remove(it);
return true;
}
break;

const CarlaMutexLocker cml(fMidiOutMutex);
case kExternalGraphConnectionMidiOutput: {
const CarlaMutexLocker cml(fMidiOutMutex);

for (LinkedList<MidiOutPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next())
{
static MidiOutPort fallback = { nullptr, { '\0' } };
for (LinkedList<MidiOutPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next())
{
static MidiOutPort fallback = { nullptr, { '\0' } };

MidiOutPort& outPort(it.getValue(fallback));
CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr);
MidiOutPort& outPort(it.getValue(fallback));
CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr);

if (std::strncmp(outPort.name, portName, STR_MAX) != 0)
continue;
if (std::strncmp(outPort.name, portName, STR_MAX) != 0)
continue;

outPort.port->closePort();
delete outPort.port;
outPort.port->closePort();
delete outPort.port;

fMidiOuts.remove(it);
return true;
fMidiOuts.remove(it);
return true;
}
} break;
}

return false;


+ 1
- 1
source/modules/juce_audio_devices.h View File

@@ -22,7 +22,7 @@
#include "juce_audio_basics.h"
#include "juce_audio_formats.h"

#if JUCE_MAC || JUCE_WINDOWS
#if 1 //JUCE_MAC || JUCE_WINDOWS
# include "juce_audio_devices/AppConfig.h"
# include "juce_audio_devices/juce_audio_devices.h"
#endif


Loading…
Cancel
Save