Browse Source

Cleanup and minor rework of some engine graph code

tags/1.9.6
falkTX 10 years ago
parent
commit
4018cdff82
12 changed files with 228 additions and 237 deletions
  1. +3
    -16
      source/backend/CarlaEngine.hpp
  2. +4
    -28
      source/backend/engine/CarlaEngine.cpp
  3. +124
    -105
      source/backend/engine/CarlaEngineGraph.cpp
  4. +17
    -10
      source/backend/engine/CarlaEngineGraph.hpp
  5. +47
    -13
      source/backend/engine/CarlaEngineInternal.cpp
  6. +10
    -13
      source/backend/engine/CarlaEngineInternal.hpp
  7. +5
    -4
      source/backend/engine/CarlaEngineJack.cpp
  8. +7
    -18
      source/backend/engine/CarlaEngineJuce.cpp
  9. +2
    -2
      source/backend/engine/CarlaEngineNative.cpp
  10. +4
    -15
      source/backend/engine/CarlaEngineRtAudio.cpp
  11. +2
    -2
      source/includes/lv2/atom-util.h
  12. +3
    -11
      source/utils/CarlaEngineUtils.hpp

+ 3
- 16
source/backend/CarlaEngine.hpp View File

@@ -1072,9 +1072,9 @@ protected:
*/ */
friend class CarlaPluginInstance; friend class CarlaPluginInstance;
friend class EngineInternalGraph; friend class EngineInternalGraph;
friend class PendingRtEventsRunner;
friend class ScopedActionLock; friend class ScopedActionLock;
friend class ScopedEngineEnvironmentLocker; friend class ScopedEngineEnvironmentLocker;
friend class PendingRtEventsRunner;
friend struct PatchbayGraph; friend struct PatchbayGraph;
friend struct RackGraph; friend struct RackGraph;


@@ -1097,13 +1097,6 @@ protected:
*/ */
void offlineModeChanged(const bool isOffline); void offlineModeChanged(const bool isOffline);


/*!
* Run any pending RT events.
* Must always be called at the end of audio processing.
* @note RT call
*/
void runPendingRtEvents() noexcept;

/*! /*!
* Set a plugin (stereo) peak values. * Set a plugin (stereo) peak values.
* @note RT call * @note RT call
@@ -1120,12 +1113,6 @@ protected:
*/ */
bool loadProjectInternal(juce::XmlDocument& xmlDoc); bool loadProjectInternal(juce::XmlDocument& xmlDoc);


/*!
* Lock/Unlock environment mutex, to prevent simultaneous changes from different threads.
*/
void lockEnvironment() const noexcept;
void unlockEnvironment() const noexcept;

#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Patchbay stuff // Patchbay stuff
@@ -1186,10 +1173,10 @@ public:
# endif # endif
#endif #endif


#ifndef BUILD_BRIDGE
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Bridge/Controller OSC stuff
// OSC Controller stuff


#ifndef BUILD_BRIDGE
void oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept; void oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept;
void oscSend_control_add_plugin_end(const uint pluginId) const noexcept; void oscSend_control_add_plugin_end(const uint pluginId) const noexcept;
void oscSend_control_remove_plugin(const uint pluginId) const noexcept; void oscSend_control_remove_plugin(const uint pluginId) const noexcept;


+ 4
- 28
source/backend/engine/CarlaEngine.cpp View File

@@ -640,7 +640,7 @@ bool CarlaEngine::removePlugin(const uint id)
pData->graph.removePlugin(plugin); pData->graph.removePlugin(plugin);


const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/); const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/);
const ScopedActionLock sal(pData, kEnginePostActionRemovePlugin, id, 0, lockWait);
const ScopedActionLock sal(this, kEnginePostActionRemovePlugin, id, 0, lockWait);


/* /*
for (uint i=id; i < pData->curPluginCount; ++i) for (uint i=id; i < pData->curPluginCount; ++i)
@@ -684,13 +684,13 @@ bool CarlaEngine::removeAllPlugins()


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
pData->graph.removeAllPlugins(this);
pData->graph.removeAllPlugins();
#endif #endif


const uint32_t curPluginCount(pData->curPluginCount); const uint32_t curPluginCount(pData->curPluginCount);


const bool lockWait(isRunning()); const bool lockWait(isRunning());
const ScopedActionLock sal(pData, kEnginePostActionZeroCount, 0, 0, lockWait);
const ScopedActionLock sal(this, kEnginePostActionZeroCount, 0, 0, lockWait);


callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr); callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);


@@ -831,7 +831,7 @@ bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept
} }


const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/); const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/);
const ScopedActionLock sal(pData, kEnginePostActionSwitchPlugins, idA, idB, lockWait);
const ScopedActionLock sal(this, kEnginePostActionSwitchPlugins, idA, idB, lockWait);


/* /*
CarlaPlugin* const pluginA(pData->plugins[idA].plugin); CarlaPlugin* const pluginA(pData->plugins[idA].plugin);
@@ -1486,16 +1486,6 @@ EngineEvent* CarlaEngine::getInternalEventBuffer(const bool isInput) const noexc
return isInput ? pData->events.in : pData->events.out; return isInput ? pData->events.in : pData->events.out;
} }


void CarlaEngine::lockEnvironment() const noexcept
{
pData->envMutex.lock();
}

void CarlaEngine::unlockEnvironment() const noexcept
{
pData->envMutex.unlock();
}

// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Internal stuff // Internal stuff


@@ -1566,20 +1556,6 @@ void CarlaEngine::offlineModeChanged(const bool isOfflineNow)
} }
} }


void CarlaEngine::runPendingRtEvents() noexcept
{
pData->doNextPluginAction(true);

if (pData->time.playing)
pData->time.frame += pData->bufferSize;

if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
{
pData->timeInfo.playing = pData->time.playing;
pData->timeInfo.frame = pData->time.frame;
}
}

void CarlaEngine::setPluginPeaks(const uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept void CarlaEngine::setPluginPeaks(const uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept
{ {
EnginePluginData& pluginData(pData->plugins[pluginId]); EnginePluginData& pluginData(pData->plugins[pluginId]);


+ 124
- 105
source/backend/engine/CarlaEngineGraph.cpp View File

@@ -151,16 +151,17 @@ uint RackGraph::MIDI::getPortId(const bool isInput, const char portName[], bool*
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// RackGraph // RackGraph


RackGraph::RackGraph(const uint32_t bufferSize, const uint32_t ins, const uint32_t outs) noexcept
RackGraph::RackGraph(CarlaEngine* const engine, const uint32_t ins, const uint32_t outs) noexcept
: connections(), : connections(),
inputs(ins), inputs(ins),
outputs(outs), outputs(outs),
isOffline(false), isOffline(false),
retCon(), retCon(),
audio(), audio(),
midi()
midi(),
kEngine(engine)
{ {
setBufferSize(bufferSize);
setBufferSize(engine->getBufferSize());
} }


RackGraph::~RackGraph() noexcept RackGraph::~RackGraph() noexcept
@@ -224,10 +225,8 @@ void RackGraph::setOffline(const bool offline) noexcept
isOffline = offline; isOffline = offline;
} }


bool RackGraph::connect(CarlaEngine* const engine, const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept
bool RackGraph::connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept
{ {
CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);

uint otherGroup, otherPort, carlaPort; uint otherGroup, otherPort, carlaPort;


if (groupA == RACK_GRAPH_GROUP_CARLA) if (groupA == RACK_GRAPH_GROUP_CARLA)
@@ -285,19 +284,19 @@ bool RackGraph::connect(CarlaEngine* const engine, const uint groupA, const uint
case RACK_GRAPH_CARLA_PORT_MIDI_IN: case RACK_GRAPH_CARLA_PORT_MIDI_IN:
CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_MIDI_IN, false); CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_MIDI_IN, false);
if (const char* const portName = midi.getName(true, otherPort)) if (const char* const portName = midi.getName(true, otherPort))
makeConnection = engine->connectRackMidiInPort(portName);
makeConnection = kEngine->connectRackMidiInPort(portName);
break; break;


case RACK_GRAPH_CARLA_PORT_MIDI_OUT: case RACK_GRAPH_CARLA_PORT_MIDI_OUT:
CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_MIDI_OUT, false); CARLA_SAFE_ASSERT_RETURN(otherGroup == RACK_GRAPH_GROUP_MIDI_OUT, false);
if (const char* const portName = midi.getName(false, otherPort)) if (const char* const portName = midi.getName(false, otherPort))
makeConnection = engine->connectRackMidiOutPort(portName);
makeConnection = kEngine->connectRackMidiOutPort(portName);
break; break;
} }


if (! makeConnection) if (! makeConnection)
{ {
engine->setLastError("Invalid rack connection");
kEngine->setLastError("Invalid rack connection");
return false; return false;
} }


@@ -308,15 +307,14 @@ bool RackGraph::connect(CarlaEngine* const engine, const uint groupA, const uint
strBuf[STR_MAX] = '\0'; strBuf[STR_MAX] = '\0';
std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB); std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB);


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


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


bool RackGraph::disconnect(CarlaEngine* const engine, const uint connectionId) noexcept
bool RackGraph::disconnect(const uint connectionId) noexcept
{ {
CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(connections.list.count() > 0, false); CARLA_SAFE_ASSERT_RETURN(connections.list.count() > 0, false);


for (LinkedList<ConnectionToId>::Itenerator it=connections.list.begin(); it.valid(); it.next()) for (LinkedList<ConnectionToId>::Itenerator it=connections.list.begin(); it.valid(); it.next())
@@ -381,28 +379,28 @@ bool RackGraph::disconnect(CarlaEngine* const engine, const uint connectionId) n


case RACK_GRAPH_CARLA_PORT_MIDI_IN: case RACK_GRAPH_CARLA_PORT_MIDI_IN:
if (const char* const portName = midi.getName(true, otherPort)) if (const char* const portName = midi.getName(true, otherPort))
makeDisconnection = engine->disconnectRackMidiInPort(portName);
makeDisconnection = kEngine->disconnectRackMidiInPort(portName);
break; break;


case RACK_GRAPH_CARLA_PORT_MIDI_OUT: case RACK_GRAPH_CARLA_PORT_MIDI_OUT:
if (const char* const portName = midi.getName(false, otherPort)) if (const char* const portName = midi.getName(false, otherPort))
makeDisconnection = engine->disconnectRackMidiOutPort(portName);
makeDisconnection = kEngine->disconnectRackMidiOutPort(portName);
break; break;
} }


if (! makeDisconnection) if (! makeDisconnection)
{ {
engine->setLastError("Invalid rack connection");
kEngine->setLastError("Invalid rack connection");
return false; return false;
} }


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


connections.list.remove(it); connections.list.remove(it);
return true; return true;
} }


engine->setLastError("Failed to find connection");
kEngine->setLastError("Failed to find connection");
return false; return false;
} }


@@ -421,6 +419,29 @@ void RackGraph::clearConnections() noexcept
midi.outs.clear(); midi.outs.clear();
} }


void RackGraph::refreshConnections(const char* const deviceName)
{
CARLA_SAFE_ASSERT_RETURN(deviceName != nullptr,);

connections.clear();

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

kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_IN1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_IN2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_OUT1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_OUT2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_MIDI_IN, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in");
kEngine->callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_MIDI_OUT, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out");
}

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

}

const char* const* RackGraph::getConnections() const noexcept const char* const* RackGraph::getConnections() const noexcept
{ {
if (connections.list.count() == 0) if (connections.list.count() == 0)
@@ -916,8 +937,9 @@ void removeNodeFromPatchbay(CarlaEngine* const engine, const uint32_t groupId, c
class CarlaPluginInstance : public AudioPluginInstance class CarlaPluginInstance : public AudioPluginInstance
{ {
public: public:
CarlaPluginInstance(CarlaPlugin* const plugin)
: fPlugin(plugin),
CarlaPluginInstance(CarlaEngine* const engine, CarlaPlugin* const plugin)
: kEngine(engine),
fPlugin(plugin),
leakDetector_CarlaPluginInstance() leakDetector_CarlaPluginInstance()
{ {
setPlayConfigDetails(static_cast<int>(fPlugin->getAudioInCount()), setPlayConfigDetails(static_cast<int>(fPlugin->getAudioInCount()),
@@ -985,10 +1007,7 @@ public:
return; return;
} }


CarlaEngine* const engine(fPlugin->getEngine());
CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);

if (! fPlugin->tryLock(engine->isOffline()))
if (! fPlugin->tryLock(kEngine->isOffline()))
{ {
audio.clear(); audio.clear();
midi.clear(); midi.clear();
@@ -1049,7 +1068,7 @@ public:
} }
} }


engine->setPluginPeaks(fPlugin->getId(), inPeaks, outPeaks);
kEngine->setPluginPeaks(fPlugin->getId(), inPeaks, outPeaks);
} }
else else
{ {
@@ -1120,6 +1139,7 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------


private: private:
CarlaEngine* const kEngine;
CarlaPlugin* fPlugin; CarlaPlugin* fPlugin;


CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginInstance) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginInstance)
@@ -1128,7 +1148,7 @@ private:
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Patchbay Graph // Patchbay Graph


PatchbayGraph::PatchbayGraph(const int bufferSize, const double sampleRate, const uint32_t ins, const uint32_t outs)
PatchbayGraph::PatchbayGraph(CarlaEngine* const engine, const uint32_t ins, const uint32_t outs)
: connections(), : connections(),
graph(), graph(),
audioBuffer(), audioBuffer(),
@@ -1136,8 +1156,12 @@ PatchbayGraph::PatchbayGraph(const int bufferSize, const double sampleRate, cons
inputs(carla_fixValue(0U, MAX_PATCHBAY_PLUGINS-2, ins)), inputs(carla_fixValue(0U, MAX_PATCHBAY_PLUGINS-2, ins)),
outputs(carla_fixValue(0U, MAX_PATCHBAY_PLUGINS-2, outs)), outputs(carla_fixValue(0U, MAX_PATCHBAY_PLUGINS-2, outs)),
ignorePathbay(false), ignorePathbay(false),
retCon()
retCon(),
kEngine(engine)
{ {
const int bufferSize(static_cast<int>(engine->getBufferSize()));
const double sampleRate(engine->getSampleRate());

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


@@ -1194,14 +1218,14 @@ PatchbayGraph::~PatchbayGraph()
void PatchbayGraph::setBufferSize(const int bufferSize) void PatchbayGraph::setBufferSize(const int bufferSize)
{ {
graph.releaseResources(); graph.releaseResources();
graph.prepareToPlay(graph.getSampleRate(), bufferSize);
graph.prepareToPlay(kEngine->getSampleRate(), bufferSize);
audioBuffer.setSize(audioBuffer.getNumChannels(), bufferSize); audioBuffer.setSize(audioBuffer.getNumChannels(), bufferSize);
} }


void PatchbayGraph::setSampleRate(const double sampleRate) void PatchbayGraph::setSampleRate(const double sampleRate)
{ {
graph.releaseResources(); graph.releaseResources();
graph.prepareToPlay(sampleRate, graph.getBlockSize());
graph.prepareToPlay(sampleRate, static_cast<int>(kEngine->getBufferSize()));
} }


void PatchbayGraph::setOffline(const bool offline) void PatchbayGraph::setOffline(const bool offline)
@@ -1214,7 +1238,7 @@ void PatchbayGraph::addPlugin(CarlaPlugin* const plugin)
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
carla_debug("PatchbayGraph::addPlugin(%p)", plugin); carla_debug("PatchbayGraph::addPlugin(%p)", plugin);


CarlaPluginInstance* const instance(new CarlaPluginInstance(plugin));
CarlaPluginInstance* const instance(new CarlaPluginInstance(kEngine, plugin));
AudioProcessorGraph::Node* const node(graph.addNode(instance)); AudioProcessorGraph::Node* const node(graph.addNode(instance));
CARLA_SAFE_ASSERT_RETURN(node != nullptr,); CARLA_SAFE_ASSERT_RETURN(node != nullptr,);


@@ -1234,23 +1258,20 @@ void PatchbayGraph::replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* con
CARLA_SAFE_ASSERT_RETURN(oldPlugin != newPlugin,); CARLA_SAFE_ASSERT_RETURN(oldPlugin != newPlugin,);
CARLA_SAFE_ASSERT_RETURN(oldPlugin->getId() == newPlugin->getId(),); CARLA_SAFE_ASSERT_RETURN(oldPlugin->getId() == newPlugin->getId(),);


CarlaEngine* const engine(oldPlugin->getEngine());
CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);

AudioProcessorGraph::Node* const oldNode(graph.getNodeForId(oldPlugin->getPatchbayNodeId())); AudioProcessorGraph::Node* const oldNode(graph.getNodeForId(oldPlugin->getPatchbayNodeId()));
CARLA_SAFE_ASSERT_RETURN(oldNode != nullptr,); CARLA_SAFE_ASSERT_RETURN(oldNode != nullptr,);


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


((CarlaPluginInstance*)oldNode->getProcessor())->invalidatePlugin(); ((CarlaPluginInstance*)oldNode->getProcessor())->invalidatePlugin();


graph.removeNode(oldNode->nodeId); graph.removeNode(oldNode->nodeId);


CarlaPluginInstance* const instance(new CarlaPluginInstance(newPlugin));
CarlaPluginInstance* const instance(new CarlaPluginInstance(kEngine, newPlugin));
AudioProcessorGraph::Node* const node(graph.addNode(instance)); AudioProcessorGraph::Node* const node(graph.addNode(instance));
CARLA_SAFE_ASSERT_RETURN(node != nullptr,); CARLA_SAFE_ASSERT_RETURN(node != nullptr,);


@@ -1268,24 +1289,21 @@ void PatchbayGraph::removePlugin(CarlaPlugin* const plugin)
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
carla_debug("PatchbayGraph::removePlugin(%p)", plugin); carla_debug("PatchbayGraph::removePlugin(%p)", plugin);


CarlaEngine* const engine(plugin->getEngine());
CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);

AudioProcessorGraph::Node* const node(graph.getNodeForId(plugin->getPatchbayNodeId())); AudioProcessorGraph::Node* const node(graph.getNodeForId(plugin->getPatchbayNodeId()));
CARLA_SAFE_ASSERT_RETURN(node != nullptr,); CARLA_SAFE_ASSERT_RETURN(node != nullptr,);


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


((CarlaPluginInstance*)node->getProcessor())->invalidatePlugin(); ((CarlaPluginInstance*)node->getProcessor())->invalidatePlugin();


// Fix plugin Ids properties // Fix plugin Ids properties
for (uint i=plugin->getId()+1, count=engine->getCurrentPluginCount(); i<count; ++i)
for (uint i=plugin->getId()+1, count=kEngine->getCurrentPluginCount(); i<count; ++i)
{ {
CarlaPlugin* const plugin2(engine->getPlugin(i));
CarlaPlugin* const plugin2(kEngine->getPlugin(i));
CARLA_SAFE_ASSERT_BREAK(plugin2 != nullptr); CARLA_SAFE_ASSERT_BREAK(plugin2 != nullptr);


if (AudioProcessorGraph::Node* const node2 = graph.getNodeForId(plugin2->getPatchbayNodeId())) if (AudioProcessorGraph::Node* const node2 = graph.getNodeForId(plugin2->getPatchbayNodeId()))
@@ -1298,14 +1316,13 @@ void PatchbayGraph::removePlugin(CarlaPlugin* const plugin)
CARLA_SAFE_ASSERT_RETURN(graph.removeNode(node->nodeId),); CARLA_SAFE_ASSERT_RETURN(graph.removeNode(node->nodeId),);
} }


void PatchbayGraph::removeAllPlugins(CarlaEngine* const engine)
void PatchbayGraph::removeAllPlugins()
{ {
CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);
carla_debug("PatchbayGraph::removeAllPlugins(%p)", engine);
carla_debug("PatchbayGraph::removeAllPlugins()");


for (uint i=0, count=engine->getCurrentPluginCount(); i<count; ++i)
for (uint i=0, count=kEngine->getCurrentPluginCount(); i<count; ++i)
{ {
CarlaPlugin* const plugin(engine->getPlugin(i));
CarlaPlugin* const plugin(kEngine->getPlugin(i));
CARLA_SAFE_ASSERT_CONTINUE(plugin != nullptr); CARLA_SAFE_ASSERT_CONTINUE(plugin != nullptr);


AudioProcessorGraph::Node* const node(graph.getNodeForId(plugin->getPatchbayNodeId())); AudioProcessorGraph::Node* const node(graph.getNodeForId(plugin->getPatchbayNodeId()));
@@ -1313,8 +1330,8 @@ void PatchbayGraph::removeAllPlugins(CarlaEngine* const engine)


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


((CarlaPluginInstance*)node->getProcessor())->invalidatePlugin(); ((CarlaPluginInstance*)node->getProcessor())->invalidatePlugin();
@@ -1323,10 +1340,8 @@ void PatchbayGraph::removeAllPlugins(CarlaEngine* const engine)
} }
} }


bool PatchbayGraph::connect(CarlaEngine* const engine, const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept
bool PatchbayGraph::connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept
{ {
CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);

uint adjustedPortA = portA; uint adjustedPortA = portA;
uint adjustedPortB = portB; uint adjustedPortB = portB;


@@ -1337,7 +1352,7 @@ bool PatchbayGraph::connect(CarlaEngine* const engine, const uint groupA, const


if (! graph.addConnection(groupA, static_cast<int>(adjustedPortA), groupB, static_cast<int>(adjustedPortB))) if (! graph.addConnection(groupA, static_cast<int>(adjustedPortA), groupB, static_cast<int>(adjustedPortB)))
{ {
engine->setLastError("Failed from juce");
kEngine->setLastError("Failed from juce");
return false; return false;
} }


@@ -1348,16 +1363,14 @@ bool PatchbayGraph::connect(CarlaEngine* const engine, const uint groupA, const
strBuf[STR_MAX] = '\0'; strBuf[STR_MAX] = '\0';
std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB); std::snprintf(strBuf, STR_MAX, "%u:%u:%u:%u", groupA, portA, groupB, portB);


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


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


bool PatchbayGraph::disconnect(CarlaEngine* const engine, const uint connectionId) noexcept
bool PatchbayGraph::disconnect(const uint connectionId) noexcept
{ {
CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false);

for (LinkedList<ConnectionToId>::Itenerator it=connections.list.begin(); it.valid(); it.next()) for (LinkedList<ConnectionToId>::Itenerator it=connections.list.begin(); it.valid(); it.next())
{ {
static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; static const ConnectionToId fallback = { 0, 0, 0, 0, 0 };
@@ -1380,20 +1393,18 @@ bool PatchbayGraph::disconnect(CarlaEngine* const engine, const uint connectionI
connectionToId.groupB, static_cast<int>(adjustedPortB))) connectionToId.groupB, static_cast<int>(adjustedPortB)))
return false; return false;


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


connections.list.remove(it); connections.list.remove(it);
return true; return true;
} }


engine->setLastError("Failed to find connection");
kEngine->setLastError("Failed to find connection");
return false; return false;
} }


void PatchbayGraph::disconnectGroup(CarlaEngine* const engine, const uint groupId) noexcept
void PatchbayGraph::disconnectGroup(const uint groupId) noexcept
{ {
CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);

for (LinkedList<ConnectionToId>::Itenerator it=connections.list.begin(); it.valid(); it.next()) for (LinkedList<ConnectionToId>::Itenerator it=connections.list.begin(); it.valid(); it.next())
{ {
static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; static const ConnectionToId fallback = { 0, 0, 0, 0, 0 };
@@ -1417,7 +1428,7 @@ void PatchbayGraph::disconnectGroup(CarlaEngine* const engine, const uint groupI
connectionToId.groupB, static_cast<int>(adjustedPortB)); connectionToId.groupB, static_cast<int>(adjustedPortB));
*/ */


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


connections.list.remove(it); connections.list.remove(it);
} }
@@ -1431,28 +1442,30 @@ void PatchbayGraph::clearConnections()
graph.removeConnection(0); graph.removeConnection(0);
} }


void PatchbayGraph::refreshConnections(CarlaEngine* const engine)
void PatchbayGraph::refreshConnections(const char* const deviceName)
{ {
CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);
CARLA_SAFE_ASSERT_RETURN(deviceName != nullptr,);


connections.clear(); connections.clear();
graph.removeIllegalConnections(); graph.removeIllegalConnections();


for (int i=0, count=graph.getNumNodes(); i<count; ++i)
if (! ignorePathbay)
{ {
AudioProcessorGraph::Node* const node(graph.getNode(i));
CARLA_SAFE_ASSERT_CONTINUE(node != nullptr);
for (int i=0, count=graph.getNumNodes(); i<count; ++i)
{
AudioProcessorGraph::Node* const node(graph.getNode(i));
CARLA_SAFE_ASSERT_CONTINUE(node != nullptr);


AudioProcessor* const proc(node->getProcessor());
CARLA_SAFE_ASSERT_CONTINUE(proc != nullptr);
AudioProcessor* const proc(node->getProcessor());
CARLA_SAFE_ASSERT_CONTINUE(proc != nullptr);


int clientId = -1;
int clientId = -1;


if (node->properties.getWithDefault("isPlugin", false) == juce::var(true))
clientId = node->properties.getWithDefault("pluginId", -1);
if (node->properties.getWithDefault("isPlugin", false) == juce::var(true))
clientId = node->properties.getWithDefault("pluginId", -1);


if (! ignorePathbay)
addNodeToPatchbay(engine, node->nodeId, clientId, proc);
addNodeToPatchbay(kEngine, node->nodeId, clientId, proc);
}
} }


char strBuf[STR_MAX+1]; char strBuf[STR_MAX+1];
@@ -1486,7 +1499,7 @@ void PatchbayGraph::refreshConnections(CarlaEngine* const engine)
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", groupA, portA, groupB, portB); std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", groupA, portA, groupB, portB);
strBuf[STR_MAX] = '\0'; strBuf[STR_MAX] = '\0';


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


connections.list.append(connectionToId); connections.list.append(connectionToId);
} }
@@ -1633,9 +1646,10 @@ void PatchbayGraph::process(CarlaEngine::ProtectedData* const data, const float*
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// InternalGraph // InternalGraph


EngineInternalGraph::EngineInternalGraph() noexcept
EngineInternalGraph::EngineInternalGraph(CarlaEngine* const engine) noexcept
: fIsRack(true), : fIsRack(true),
fIsReady(false)
fIsReady(false),
kEngine(engine)
{ {
fRack = nullptr; fRack = nullptr;
} }
@@ -1646,19 +1660,19 @@ EngineInternalGraph::~EngineInternalGraph() noexcept
CARLA_SAFE_ASSERT(fRack == nullptr); CARLA_SAFE_ASSERT(fRack == nullptr);
} }


void EngineInternalGraph::create(const bool isRack, const double sampleRate, const uint32_t bufferSize, const uint32_t inputs, const uint32_t outputs)
void EngineInternalGraph::create(const uint32_t inputs, const uint32_t outputs)
{ {
fIsRack = isRack;
fIsRack = (kEngine->getOptions().processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK);


if (isRack)
if (fIsRack)
{ {
CARLA_SAFE_ASSERT_RETURN(fRack == nullptr,); CARLA_SAFE_ASSERT_RETURN(fRack == nullptr,);
fRack = new RackGraph(bufferSize, inputs, outputs);
fRack = new RackGraph(kEngine, inputs, outputs);
} }
else else
{ {
CARLA_SAFE_ASSERT_RETURN(fPatchbay == nullptr,); CARLA_SAFE_ASSERT_RETURN(fPatchbay == nullptr,);
fPatchbay = new PatchbayGraph(static_cast<int>(bufferSize), sampleRate, inputs, outputs);
fPatchbay = new PatchbayGraph(kEngine, inputs, outputs);
} }


fIsReady = true; fIsReady = true;
@@ -1672,8 +1686,6 @@ void EngineInternalGraph::destroy() noexcept
return; return;
} }


fIsReady = false;

if (fIsRack) if (fIsRack)
{ {
CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,); CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
@@ -1686,6 +1698,8 @@ void EngineInternalGraph::destroy() noexcept
delete fPatchbay; delete fPatchbay;
fPatchbay = nullptr; fPatchbay = nullptr;
} }

fIsReady = false;
} }


void EngineInternalGraph::setBufferSize(const uint32_t bufferSize) void EngineInternalGraph::setBufferSize(const uint32_t bufferSize)
@@ -1797,10 +1811,10 @@ void EngineInternalGraph::removePlugin(CarlaPlugin* const plugin)
fPatchbay->removePlugin(plugin); fPatchbay->removePlugin(plugin);
} }


void EngineInternalGraph::removeAllPlugins(CarlaEngine* const engine)
void EngineInternalGraph::removeAllPlugins()
{ {
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,); CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
fPatchbay->removeAllPlugins(engine);
fPatchbay->removeAllPlugins();
} }


void EngineInternalGraph::setIgnorePatchbay(const bool ignore) noexcept void EngineInternalGraph::setIgnorePatchbay(const bool ignore) noexcept
@@ -1821,12 +1835,12 @@ bool CarlaEngine::patchbayConnect(const uint groupA, const uint portA, const uin
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{ {
if (RackGraph* const graph = pData->graph.getRackGraph()) if (RackGraph* const graph = pData->graph.getRackGraph())
return graph->connect(this, groupA, portA, groupB, portB);
return graph->connect(groupA, portA, groupB, portB);
} }
else else
{ {
if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph()) if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph())
return graph->connect(this, groupA, portA, groupB, portB);
return graph->connect(groupA, portA, groupB, portB);
} }


return false; return false;
@@ -1841,12 +1855,12 @@ bool CarlaEngine::patchbayDisconnect(const uint connectionId)
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{ {
if (RackGraph* const graph = pData->graph.getRackGraph()) if (RackGraph* const graph = pData->graph.getRackGraph())
return graph->disconnect(this, connectionId);
return graph->disconnect(connectionId);
} }
else else
{ {
if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph()) if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph())
return graph->disconnect(this, connectionId);
return graph->disconnect(connectionId);
} }


return false; return false;
@@ -1857,6 +1871,7 @@ bool CarlaEngine::patchbayRefresh(const bool external)
// subclasses should handle this // subclasses should handle this
CARLA_SAFE_ASSERT_RETURN(! external, false); CARLA_SAFE_ASSERT_RETURN(! external, false);


// FIXME
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{ {
// This is implemented in engine subclasses for MIDI support // This is implemented in engine subclasses for MIDI support
@@ -1864,12 +1879,16 @@ bool CarlaEngine::patchbayRefresh(const bool external)
return false; return false;
} }


CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY, false);

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

graph->refreshConnections(this);
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
if (RackGraph* const graph = pData->graph.getRackGraph())
graph->refreshConnections("");
}
else
{
if (PatchbayGraph* const graph = pData->graph.getPatchbayGraph())
graph->refreshConnections("");
}


return true; return true;
} }
@@ -1895,12 +1914,12 @@ const char* const* CarlaEngine::getPatchbayConnections() const
return nullptr; return nullptr;
} }


void CarlaEngine::restorePatchbayConnection(const char* const connSource, const char* const connTarget)
void CarlaEngine::restorePatchbayConnection(const char* const sourcePort, const char* const targetPort)
{ {
CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(),); CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(),);
CARLA_SAFE_ASSERT_RETURN(connSource != nullptr && connSource[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(connTarget != nullptr && connTarget[0] != '\0',);
carla_debug("CarlaEngine::restorePatchbayConnection(\"%s\", \"%s\")", connSource, connTarget);
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);


uint groupA, portA; uint groupA, portA;
uint groupB, portB; uint groupB, portB;
@@ -1910,9 +1929,9 @@ void CarlaEngine::restorePatchbayConnection(const char* const connSource, const
RackGraph* const graph = pData->graph.getRackGraph(); RackGraph* const graph = pData->graph.getRackGraph();
CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,);


if (! graph->getGroupAndPortIdFromFullName(connSource, groupA, portA))
if (! graph->getGroupAndPortIdFromFullName(sourcePort, groupA, portA))
return; return;
if (! graph->getGroupAndPortIdFromFullName(connTarget, groupB, portB))
if (! graph->getGroupAndPortIdFromFullName(targetPort, groupB, portB))
return; return;
} }
else else
@@ -1920,9 +1939,9 @@ void CarlaEngine::restorePatchbayConnection(const char* const connSource, const
PatchbayGraph* const graph = pData->graph.getPatchbayGraph(); PatchbayGraph* const graph = pData->graph.getPatchbayGraph();
CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,);


if (! graph->getGroupAndPortIdFromFullName(connSource, groupA, portA))
if (! graph->getGroupAndPortIdFromFullName(sourcePort, groupA, portA))
return; return;
if (! graph->getGroupAndPortIdFromFullName(connTarget, groupB, portB))
if (! graph->getGroupAndPortIdFromFullName(targetPort, groupB, portB))
return; return;
} }




+ 17
- 10
source/backend/engine/CarlaEngineGraph.hpp View File

@@ -90,15 +90,16 @@ struct RackGraph {
CARLA_DECLARE_NON_COPY_CLASS(MIDI) CARLA_DECLARE_NON_COPY_CLASS(MIDI)
} midi; } midi;


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


void setBufferSize(const uint32_t bufferSize) noexcept; void setBufferSize(const uint32_t bufferSize) noexcept;
void setOffline(const bool offline) noexcept; void setOffline(const bool offline) noexcept;


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


const char* const* getConnections() const noexcept; const char* const* getConnections() const noexcept;
bool getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const noexcept; bool getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const noexcept;
@@ -108,12 +109,15 @@ struct RackGraph {


// extended, will call process() in the middle // extended, will call process() in the middle
void processHelper(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames); void processHelper(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames);

CarlaEngine* const kEngine;
CARLA_DECLARE_NON_COPY_CLASS(RackGraph)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// PatchbayGraph // PatchbayGraph


struct PatchbayGraph {
struct PatchbayGraph {
PatchbayConnectionList connections; PatchbayConnectionList connections;
AudioProcessorGraph graph; AudioProcessorGraph graph;
AudioSampleBuffer audioBuffer; AudioSampleBuffer audioBuffer;
@@ -123,7 +127,7 @@ struct PatchbayGraph {
bool ignorePathbay; bool ignorePathbay;
mutable CharStringListPtr retCon; mutable CharStringListPtr retCon;


PatchbayGraph(const int bufferSize, const double sampleRate, const uint32_t inputs, const uint32_t outputs);
PatchbayGraph(CarlaEngine* const engine, const uint32_t inputs, const uint32_t outputs);
~PatchbayGraph(); ~PatchbayGraph();


void setBufferSize(const int bufferSize); void setBufferSize(const int bufferSize);
@@ -133,18 +137,21 @@ struct PatchbayGraph {
void addPlugin(CarlaPlugin* const plugin); void addPlugin(CarlaPlugin* const plugin);
void replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* const newPlugin); void replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* const newPlugin);
void removePlugin(CarlaPlugin* const plugin); void removePlugin(CarlaPlugin* const plugin);
void removeAllPlugins(CarlaEngine* const engine);
void removeAllPlugins();


bool connect(CarlaEngine* const engine, const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept;
bool disconnect(CarlaEngine* const engine, const uint connectionId) noexcept;
void disconnectGroup(CarlaEngine* const engine, const uint groupId) noexcept;
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 clearConnections(); void clearConnections();
void refreshConnections(CarlaEngine* const engine);
void refreshConnections(const char* const deviceName);


const char* const* getConnections() const; const char* const* getConnections() const;
bool getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) 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); void process(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const int frames);

CarlaEngine* const kEngine;
CARLA_DECLARE_NON_COPY_CLASS(PatchbayGraph)
}; };


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


+ 47
- 13
source/backend/engine/CarlaEngineInternal.cpp View File

@@ -121,7 +121,7 @@ CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) noexcept
#endif #endif
events(), events(),
#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
graph(),
graph(engine),
#endif #endif
time(), time(),
nextAction() nextAction()
@@ -337,40 +337,74 @@ void CarlaEngine::ProtectedData::doNextPluginAction(const bool unlock) noexcept
} }
} }


// -----------------------------------------------------------------------
// PendingRtEventsRunner

PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine) noexcept
: pData(engine->pData) {}

PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
{
pData->doNextPluginAction(true);

if (pData->time.playing)
pData->time.frame += pData->bufferSize;

if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
{
pData->timeInfo.playing = pData->time.playing;
pData->timeInfo.frame = pData->time.frame;
}
}

// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// ScopedActionLock // ScopedActionLock


ScopedActionLock::ScopedActionLock(CarlaEngine::ProtectedData* const data, const EnginePostAction action, const uint pluginId, const uint value, const bool lockWait) noexcept
: fData(data)
ScopedActionLock::ScopedActionLock(CarlaEngine* const engine, const EnginePostAction action, const uint pluginId, const uint value, const bool lockWait) noexcept
: pData(engine->pData)
{ {
CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,); CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);


fData->nextAction.mutex.lock();
pData->nextAction.mutex.lock();


CARLA_SAFE_ASSERT_RETURN(fData->nextAction.opcode == kEnginePostActionNull,);
CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);


fData->nextAction.opcode = action;
fData->nextAction.pluginId = pluginId;
fData->nextAction.value = value;
pData->nextAction.opcode = action;
pData->nextAction.pluginId = pluginId;
pData->nextAction.value = value;


if (lockWait) if (lockWait)
{ {
// block wait for unlock on processing side // block wait for unlock on processing side
carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId); carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId);
fData->nextAction.mutex.lock();
pData->nextAction.mutex.lock();
carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId); carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId);
} }
else else
{ {
fData->doNextPluginAction(false);
pData->doNextPluginAction(false);
} }
} }


ScopedActionLock::~ScopedActionLock() noexcept ScopedActionLock::~ScopedActionLock() noexcept
{ {
CARLA_SAFE_ASSERT(fData->nextAction.opcode == kEnginePostActionNull);
fData->nextAction.mutex.tryLock();
fData->nextAction.mutex.unlock();
CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull);
pData->nextAction.mutex.tryLock();
pData->nextAction.mutex.unlock();
}

// -----------------------------------------------------------------------
// ScopedEngineEnvironmentLocker

ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
: pData(engine->pData)
{
pData->envMutex.lock();
}

ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept
{
pData->envMutex.unlock();
} }


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


+ 10
- 13
source/backend/engine/CarlaEngineInternal.hpp View File

@@ -60,10 +60,10 @@ struct PatchbayGraph;
class EngineInternalGraph class EngineInternalGraph
{ {
public: public:
EngineInternalGraph() noexcept;
EngineInternalGraph(CarlaEngine* const engine) noexcept;
~EngineInternalGraph() noexcept; ~EngineInternalGraph() noexcept;


void create(const bool isRack, const double sampleRate, const uint32_t bufferSize, const uint32_t inputs, const uint32_t outputs);
void create(const uint32_t inputs, const uint32_t outputs);
void destroy() noexcept; void destroy() noexcept;


void setBufferSize(const uint32_t bufferSize); void setBufferSize(const uint32_t bufferSize);
@@ -84,7 +84,7 @@ public:
void addPlugin(CarlaPlugin* const plugin); void addPlugin(CarlaPlugin* const plugin);
void replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* const newPlugin); void replacePlugin(CarlaPlugin* const oldPlugin, CarlaPlugin* const newPlugin);
void removePlugin(CarlaPlugin* const plugin); void removePlugin(CarlaPlugin* const plugin);
void removeAllPlugins(CarlaEngine* const engine);
void removeAllPlugins();


void setIgnorePatchbay(const bool ignore) noexcept; void setIgnorePatchbay(const bool ignore) noexcept;


@@ -97,6 +97,8 @@ private:
PatchbayGraph* fPatchbay; PatchbayGraph* fPatchbay;
}; };


CarlaEngine* const kEngine;

CARLA_PREVENT_HEAP_ALLOCATION CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalGraph) CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalGraph)
}; };
@@ -230,16 +232,11 @@ struct CarlaEngine::ProtectedData {
class PendingRtEventsRunner class PendingRtEventsRunner
{ {
public: public:
PendingRtEventsRunner(CarlaEngine* const engine) noexcept
: fEngine(engine) {}

~PendingRtEventsRunner() noexcept
{
fEngine->runPendingRtEvents();
}
PendingRtEventsRunner(CarlaEngine* const engine) noexcept;
~PendingRtEventsRunner() noexcept;


private: private:
CarlaEngine* const fEngine;
CarlaEngine::ProtectedData* const pData;


CARLA_PREVENT_HEAP_ALLOCATION CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(PendingRtEventsRunner) CARLA_DECLARE_NON_COPY_CLASS(PendingRtEventsRunner)
@@ -250,11 +247,11 @@ private:
class ScopedActionLock class ScopedActionLock
{ {
public: public:
ScopedActionLock(CarlaEngine::ProtectedData* const data, const EnginePostAction action, const uint pluginId, const uint value, const bool lockWait) noexcept;
ScopedActionLock(CarlaEngine* const engine, const EnginePostAction action, const uint pluginId, const uint value, const bool lockWait) noexcept;
~ScopedActionLock() noexcept; ~ScopedActionLock() noexcept;


private: private:
CarlaEngine::ProtectedData* const fData;
CarlaEngine::ProtectedData* const pData;


CARLA_PREVENT_HEAP_ALLOCATION CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(ScopedActionLock) CARLA_DECLARE_NON_COPY_CLASS(ScopedActionLock)


+ 5
- 4
source/backend/engine/CarlaEngineJack.cpp View File

@@ -437,7 +437,7 @@ private:
// Jack Engine client // Jack Engine client


class CarlaEngineJackClient : public CarlaEngineClient, class CarlaEngineJackClient : public CarlaEngineClient,
JackPortDeletionCallback
private JackPortDeletionCallback
{ {
public: public:
CarlaEngineJackClient(const CarlaEngine& engine, jack_client_t* const jackClient) CarlaEngineJackClient(const CarlaEngine& engine, jack_client_t* const jackClient)
@@ -816,11 +816,11 @@ public:


if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{ {
pData->graph.create(true, pData->sampleRate, pData->bufferSize, 0, 0);
pData->graph.create(0, 0);
} }
else else
{ {
pData->graph.create(false, pData->sampleRate, pData->bufferSize, 2, 2);
pData->graph.create(2, 2);
patchbayRefresh(false); patchbayRefresh(false);
} }
} }
@@ -1701,6 +1701,8 @@ protected:


void handleJackShutdownCallback() void handleJackShutdownCallback()
{ {
const PendingRtEventsRunner prt(this);

for (uint i=0; i < pData->curPluginCount; ++i) for (uint i=0; i < pData->curPluginCount; ++i)
{ {
if (CarlaPlugin* const plugin = pData->plugins[i].plugin) if (CarlaPlugin* const plugin = pData->plugins[i].plugin)
@@ -1718,7 +1720,6 @@ protected:
#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
carla_zeroPointers(fRackPorts, kRackPortCount); carla_zeroPointers(fRackPorts, kRackPortCount);
#endif #endif
runPendingRtEvents();


callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr); callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr);
} }


+ 7
- 18
source/backend/engine/CarlaEngineJuce.cpp View File

@@ -73,6 +73,7 @@ static void initJuceDevicesIfNeeded()
// Juce Engine // Juce Engine


class CarlaEngineJuce : public CarlaEngine, class CarlaEngineJuce : public CarlaEngine,
public CarlaEngineGraphImpl,
public AudioIODeviceCallback, public AudioIODeviceCallback,
public MidiInputCallback public MidiInputCallback
{ {
@@ -175,7 +176,7 @@ public:
pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples()); pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples());
pData->sampleRate = fDevice->getCurrentSampleRate(); pData->sampleRate = fDevice->getCurrentSampleRate();


pData->graph.create(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK, pData->sampleRate, pData->bufferSize, static_cast<uint32_t>(inputNames.size()), static_cast<uint32_t>(outputNames.size()));
pData->graph.create(static_cast<uint32_t>(inputNames.size()), static_cast<uint32_t>(outputNames.size()));


fDevice->start(this); fDevice->start(this);


@@ -280,28 +281,16 @@ public:
RackGraph* const graph(pData->graph.getRackGraph()); RackGraph* const graph(pData->graph.getRackGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,);


graph->connections.clear();

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

// Main
{
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_GRAPH_GROUP_CARLA, PATCHBAY_ICON_CARLA, -1, 0.0f, getName());

callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_IN1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_IN2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_OUT1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_OUT2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_MIDI_IN, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_MIDI_OUT, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out");
}

String deviceName(fDevice->getName()); String deviceName(fDevice->getName());


if (deviceName.isNotEmpty()) if (deviceName.isNotEmpty())
deviceName = deviceName.dropLastCharacters(deviceName.fromFirstOccurrenceOf(", ", true, false).length()); deviceName = deviceName.dropLastCharacters(deviceName.fromFirstOccurrenceOf(", ", true, false).length());


graph->refreshConnections(this, deviceName.toRawUTF8());

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

// Audio In // Audio In
{ {
StringArray inputNames(fDevice->getInputChannelNames()); StringArray inputNames(fDevice->getInputChannelNames());


+ 2
- 2
source/backend/engine/CarlaEngineNative.cpp View File

@@ -604,7 +604,7 @@ public:
pData->options.preferPluginBridges = false; pData->options.preferPluginBridges = false;
pData->options.preferUiBridges = false; pData->options.preferUiBridges = false;
init("Carla-Patchbay"); init("Carla-Patchbay");
pData->graph.create(false, pData->sampleRate, pData->bufferSize, inChan, outChan);
pData->graph.create(inChan, outChan);
} }
else else
{ {
@@ -616,7 +616,7 @@ public:
pData->options.preferPluginBridges = false; pData->options.preferPluginBridges = false;
pData->options.preferUiBridges = false; pData->options.preferUiBridges = false;
init("Carla-Rack"); init("Carla-Rack");
pData->graph.create(true, pData->sampleRate, pData->bufferSize, 0, 0);
pData->graph.create(0, 0);
} }


if (pData->options.resourceDir != nullptr) if (pData->options.resourceDir != nullptr)


+ 4
- 15
source/backend/engine/CarlaEngineRtAudio.cpp View File

@@ -257,6 +257,7 @@ public:


RtAudio::StreamOptions rtOptions; RtAudio::StreamOptions rtOptions;
rtOptions.flags = RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_HOG_DEVICE | RTAUDIO_SCHEDULE_REALTIME; rtOptions.flags = RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_HOG_DEVICE | RTAUDIO_SCHEDULE_REALTIME;
rtOptions.numberOfBuffers = pData->options.audioNumPeriods;
rtOptions.streamName = clientName; rtOptions.streamName = clientName;
rtOptions.priority = 85; rtOptions.priority = 85;


@@ -292,7 +293,7 @@ public:
fAudioIntBufIn.setSize(static_cast<int>(fAudioInCount), static_cast<int>(bufferFrames)); fAudioIntBufIn.setSize(static_cast<int>(fAudioInCount), static_cast<int>(bufferFrames));
fAudioIntBufOut.setSize(static_cast<int>(fAudioOutCount), static_cast<int>(bufferFrames)); fAudioIntBufOut.setSize(static_cast<int>(fAudioOutCount), static_cast<int>(bufferFrames));


pData->graph.create(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK, pData->sampleRate, pData->bufferSize, fAudioInCount, fAudioOutCount);
pData->graph.create(fAudioInCount, fAudioOutCount);


try { try {
fAudio.startStream(); fAudio.startStream();
@@ -418,23 +419,11 @@ public:
RackGraph* const graph(pData->graph.getRackGraph()); RackGraph* const graph(pData->graph.getRackGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,);


graph->connections.clear();
graph->refreshConnections(fDeviceName.buffer());


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


// Main
{
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_GRAPH_GROUP_CARLA, PATCHBAY_ICON_CARLA, -1, 0.0f, getName());

callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_IN1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_IN2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_OUT1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_AUDIO_OUT2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_MIDI_IN, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in");
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_MIDI_OUT, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out");
}

// Audio In // Audio In
{ {
if (fDeviceName.isNotEmpty()) if (fDeviceName.isNotEmpty())
@@ -628,7 +617,7 @@ public:
PatchbayGraph* const graph(pData->graph.getPatchbayGraph()); PatchbayGraph* const graph(pData->graph.getPatchbayGraph());
CARLA_SAFE_ASSERT_RETURN(graph != nullptr,); CARLA_SAFE_ASSERT_RETURN(graph != nullptr,);


graph->refreshConnections(this);
graph->refreshConnections(fDeviceName.buffer());
} }


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


+ 2
- 2
source/includes/lv2/atom-util.h View File

@@ -94,9 +94,9 @@ lv2_atom_sequence_end(const LV2_Atom_Sequence_Body* body, uint32_t size)


/** Get an iterator pointing to the end of a Sequence body. */ /** Get an iterator pointing to the end of a Sequence body. */
static inline LV2_Atom_Event* static inline LV2_Atom_Event*
lv2_atom_sequence_end2(const LV2_Atom_Sequence_Body* body, uint32_t size)
lv2_atom_sequence_end2(LV2_Atom_Sequence_Body* body, uint32_t size)
{ {
return (LV2_Atom_Event*)((const uint8_t*)body + lv2_atom_pad_size(size));
return (LV2_Atom_Event*)((uint8_t*)body + lv2_atom_pad_size(size));
} }


/** Return true iff `i` has reached the end of `body`. */ /** Return true iff `i` has reached the end of `body`. */


+ 3
- 11
source/utils/CarlaEngineUtils.hpp View File

@@ -200,19 +200,11 @@ void fillJuceMidiBufferFromEngineEvents(juce::MidiBuffer& midiBuffer, const Engi
class ScopedEngineEnvironmentLocker class ScopedEngineEnvironmentLocker
{ {
public: public:
ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
: kEngine(engine)
{
kEngine->lockEnvironment();
}

~ScopedEngineEnvironmentLocker() noexcept
{
kEngine->unlockEnvironment();
}
ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept;
~ScopedEngineEnvironmentLocker() noexcept;


private: private:
CarlaEngine* const kEngine;
CarlaEngine::ProtectedData* const pData;


CARLA_PREVENT_HEAP_ALLOCATION CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(ScopedEngineEnvironmentLocker) CARLA_DECLARE_NON_COPY_CLASS(ScopedEngineEnvironmentLocker)


Loading…
Cancel
Save