|
|
|
@@ -1,5 +1,5 @@ |
|
|
|
--- ../Rack/src/engine/Engine.cpp 2022-02-05 22:30:09.253393116 +0000 |
|
|
|
+++ Engine.cpp 2022-02-08 02:48:26.045085405 +0000 |
|
|
|
+++ Engine.cpp 2022-02-08 18:03:08.304201743 +0000 |
|
|
|
@@ -1,3 +1,30 @@ |
|
|
|
+/* |
|
|
|
+ * DISTRHO Cardinal Plugin |
|
|
|
@@ -31,7 +31,7 @@ |
|
|
|
#include <algorithm> |
|
|
|
#include <set> |
|
|
|
#include <thread> |
|
|
|
@@ -8,181 +35,36 @@ |
|
|
|
@@ -8,181 +35,35 @@ |
|
|
|
#include <pmmintrin.h> |
|
|
|
|
|
|
|
#include <engine/Engine.hpp> |
|
|
|
@@ -131,8 +131,7 @@ |
|
|
|
-}; |
|
|
|
|
|
|
|
+// known terminal modules |
|
|
|
+extern rack::plugin::Model* modelHostAudio2; |
|
|
|
+extern rack::plugin::Model* modelHostAudio8; |
|
|
|
+extern std::vector<rack::plugin::Model*> hostTerminalModels; |
|
|
|
|
|
|
|
-/** Barrier that spin-locks until yield() is called, and then all threads switch to a mutex. |
|
|
|
-yield() should be called if it is likely that all threads will block for a while and continuing to spin-lock is unnecessary. |
|
|
|
@@ -225,7 +224,7 @@ |
|
|
|
|
|
|
|
// moduleId |
|
|
|
std::map<int64_t, Module*> modulesCache; |
|
|
|
@@ -199,6 +81,7 @@ |
|
|
|
@@ -199,6 +80,7 @@ |
|
|
|
double blockTime = 0.0; |
|
|
|
int blockFrames = 0; |
|
|
|
|
|
|
|
@@ -233,7 +232,7 @@ |
|
|
|
// Meter |
|
|
|
int meterCount = 0; |
|
|
|
double meterTotal = 0.0; |
|
|
|
@@ -206,6 +89,7 @@ |
|
|
|
@@ -206,6 +88,7 @@ |
|
|
|
double meterLastTime = -INFINITY; |
|
|
|
double meterLastAverage = 0.0; |
|
|
|
double meterLastMax = 0.0; |
|
|
|
@@ -241,7 +240,7 @@ |
|
|
|
|
|
|
|
// Parameter smoothing |
|
|
|
Module* smoothModule = NULL; |
|
|
|
@@ -217,22 +101,6 @@ |
|
|
|
@@ -217,22 +100,6 @@ |
|
|
|
Readers lock when using the engine's state. |
|
|
|
*/ |
|
|
|
SharedMutex mutex; |
|
|
|
@@ -264,7 +263,7 @@ |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
@@ -260,76 +128,11 @@ |
|
|
|
@@ -260,76 +127,11 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -342,7 +341,7 @@ |
|
|
|
// Copy all voltages from output to input |
|
|
|
for (int c = 0; c < channels; c++) { |
|
|
|
float v = output->voltages[c]; |
|
|
|
@@ -346,6 +149,53 @@ |
|
|
|
@@ -346,6 +148,53 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -396,7 +395,7 @@ |
|
|
|
/** Steps a single frame |
|
|
|
*/ |
|
|
|
static void Engine_stepFrame(Engine* that) { |
|
|
|
@@ -372,13 +222,8 @@ |
|
|
|
@@ -372,13 +221,8 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -411,7 +410,7 @@ |
|
|
|
if (module->leftExpander.messageFlipRequested) { |
|
|
|
std::swap(module->leftExpander.producerMessage, module->leftExpander.consumerMessage); |
|
|
|
module->leftExpander.messageFlipRequested = false; |
|
|
|
@@ -389,13 +234,32 @@ |
|
|
|
@@ -389,13 +233,32 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -439,41 +438,75 @@ |
|
|
|
+ Cable_step(cable); |
|
|
|
+ } |
|
|
|
+ } |
|
|
|
+ |
|
|
|
|
|
|
|
- internal->frame++; |
|
|
|
+ // Process terminal outputs last |
|
|
|
+ for (TerminalModule* terminalModule : internal->terminalModules) { |
|
|
|
+ TerminalModule__doProcess(terminalModule, processArgs, false); |
|
|
|
+ } |
|
|
|
|
|
|
|
- internal->frame++; |
|
|
|
+ |
|
|
|
+ ++internal->frame; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -425,6 +289,14 @@ |
|
|
|
disconnectedPorts.insert(&output); |
|
|
|
@@ -416,32 +279,45 @@ |
|
|
|
|
|
|
|
static void Engine_updateConnected(Engine* that) { |
|
|
|
// Find disconnected ports |
|
|
|
- std::set<Port*> disconnectedPorts; |
|
|
|
+ std::set<Input*> disconnectedInputs; |
|
|
|
+ std::set<Output*> disconnectedOutputs; |
|
|
|
for (Module* module : that->internal->modules) { |
|
|
|
for (Input& input : module->inputs) { |
|
|
|
- disconnectedPorts.insert(&input); |
|
|
|
+ disconnectedInputs.insert(&input); |
|
|
|
} |
|
|
|
} |
|
|
|
for (Output& output : module->outputs) { |
|
|
|
- disconnectedPorts.insert(&output); |
|
|
|
+ disconnectedOutputs.insert(&output); |
|
|
|
+ } |
|
|
|
+ } |
|
|
|
+ for (TerminalModule* terminalModule : that->internal->terminalModules) { |
|
|
|
+ for (Input& input : terminalModule->inputs) { |
|
|
|
+ disconnectedPorts.insert(&input); |
|
|
|
+ disconnectedInputs.insert(&input); |
|
|
|
+ } |
|
|
|
+ for (Output& output : terminalModule->outputs) { |
|
|
|
+ disconnectedPorts.insert(&output); |
|
|
|
+ } |
|
|
|
+ } |
|
|
|
+ disconnectedOutputs.insert(&output); |
|
|
|
} |
|
|
|
} |
|
|
|
for (Cable* cable : that->internal->cables) { |
|
|
|
// Connect input |
|
|
|
Input& input = cable->inputModule->inputs[cable->inputId]; |
|
|
|
@@ -442,6 +314,7 @@ |
|
|
|
- auto inputIt = disconnectedPorts.find(&input); |
|
|
|
- if (inputIt != disconnectedPorts.end()) |
|
|
|
- disconnectedPorts.erase(inputIt); |
|
|
|
+ auto inputIt = disconnectedInputs.find(&input); |
|
|
|
+ if (inputIt != disconnectedInputs.end()) |
|
|
|
+ disconnectedInputs.erase(inputIt); |
|
|
|
Port_setConnected(&input); |
|
|
|
// Connect output |
|
|
|
Output& output = cable->outputModule->outputs[cable->outputId]; |
|
|
|
- auto outputIt = disconnectedPorts.find(&output); |
|
|
|
- if (outputIt != disconnectedPorts.end()) |
|
|
|
- disconnectedPorts.erase(outputIt); |
|
|
|
+ auto outputIt = disconnectedOutputs.find(&output); |
|
|
|
+ if (outputIt != disconnectedOutputs.end()) |
|
|
|
+ disconnectedOutputs.erase(outputIt); |
|
|
|
Port_setConnected(&output); |
|
|
|
} |
|
|
|
// Disconnect ports that have no cable |
|
|
|
for (Port* port : disconnectedPorts) { |
|
|
|
Port_setDisconnected(port); |
|
|
|
+ DISTRHO_SAFE_ASSERT(port->cables.empty()); |
|
|
|
- for (Port* port : disconnectedPorts) { |
|
|
|
- Port_setDisconnected(port); |
|
|
|
+ for (Input* input : disconnectedInputs) { |
|
|
|
+ Port_setDisconnected(input); |
|
|
|
+ } |
|
|
|
+ for (Output* output : disconnectedOutputs) { |
|
|
|
+ Port_setDisconnected(output); |
|
|
|
+ DISTRHO_SAFE_ASSERT(output->cables.empty()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -460,37 +333,23 @@ |
|
|
|
@@ -460,37 +336,23 @@ |
|
|
|
|
|
|
|
Engine::Engine() { |
|
|
|
internal = new Internal; |
|
|
|
@@ -519,7 +552,7 @@ |
|
|
|
|
|
|
|
delete internal; |
|
|
|
} |
|
|
|
@@ -519,18 +378,22 @@ |
|
|
|
@@ -519,18 +381,22 @@ |
|
|
|
removeModule_NoLock(module); |
|
|
|
delete module; |
|
|
|
} |
|
|
|
@@ -545,7 +578,7 @@ |
|
|
|
random::init(); |
|
|
|
|
|
|
|
internal->blockFrame = internal->frame; |
|
|
|
@@ -543,18 +406,14 @@ |
|
|
|
@@ -543,18 +409,14 @@ |
|
|
|
Engine_updateExpander_NoLock(this, module, true); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -565,7 +598,7 @@ |
|
|
|
// Stop timer |
|
|
|
double endTime = system::getTime(); |
|
|
|
double meter = (endTime - startTime) / (frames * internal->sampleTime); |
|
|
|
@@ -572,47 +431,20 @@ |
|
|
|
@@ -572,47 +434,20 @@ |
|
|
|
internal->meterTotal = 0.0; |
|
|
|
internal->meterMax = 0.0; |
|
|
|
} |
|
|
|
@@ -615,7 +648,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -635,20 +467,13 @@ |
|
|
|
@@ -635,20 +470,13 @@ |
|
|
|
for (Module* module : internal->modules) { |
|
|
|
module->onSampleRateChange(e); |
|
|
|
} |
|
|
|
@@ -639,7 +672,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -658,7 +483,6 @@ |
|
|
|
@@ -658,7 +486,6 @@ |
|
|
|
|
|
|
|
|
|
|
|
void Engine::yieldWorkers() { |
|
|
|
@@ -647,7 +680,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -698,17 +522,25 @@ |
|
|
|
@@ -698,17 +525,25 @@ |
|
|
|
|
|
|
|
|
|
|
|
double Engine::getMeterAverage() { |
|
|
|
@@ -674,7 +707,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -718,8 +550,12 @@ |
|
|
|
@@ -718,8 +553,12 @@ |
|
|
|
for (Module* m : internal->modules) { |
|
|
|
if (i >= len) |
|
|
|
break; |
|
|
|
@@ -689,7 +722,7 @@ |
|
|
|
} |
|
|
|
return i; |
|
|
|
} |
|
|
|
@@ -728,27 +564,43 @@ |
|
|
|
@@ -728,27 +567,43 @@ |
|
|
|
std::vector<int64_t> Engine::getModuleIds() { |
|
|
|
SharedLock<SharedMutex> lock(internal->mutex); |
|
|
|
std::vector<int64_t> moduleIds; |
|
|
|
@@ -707,7 +740,7 @@ |
|
|
|
|
|
|
|
+static TerminalModule* asTerminalModule(Module* const module) { |
|
|
|
+ const plugin::Model* const model = module->model; |
|
|
|
+ if (model == modelHostAudio2 || model == modelHostAudio8) |
|
|
|
+ if (std::find(hostTerminalModels.begin(), hostTerminalModels.end(), model) != hostTerminalModels.end()) |
|
|
|
+ return static_cast<TerminalModule*>(module); |
|
|
|
+ return nullptr; |
|
|
|
+} |
|
|
|
@@ -737,7 +770,7 @@ |
|
|
|
internal->modulesCache[module->id] = module; |
|
|
|
// Dispatch AddEvent |
|
|
|
Module::AddEvent eAdd; |
|
|
|
@@ -772,11 +624,11 @@ |
|
|
|
@@ -772,11 +627,11 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -754,7 +787,7 @@ |
|
|
|
// Dispatch RemoveEvent |
|
|
|
Module::RemoveEvent eRemove; |
|
|
|
module->onRemove(eRemove); |
|
|
|
@@ -785,18 +637,14 @@ |
|
|
|
@@ -785,18 +640,14 @@ |
|
|
|
if (paramHandle->moduleId == module->id) |
|
|
|
paramHandle->module = NULL; |
|
|
|
} |
|
|
|
@@ -775,7 +808,7 @@ |
|
|
|
} |
|
|
|
// Update expanders of other modules |
|
|
|
for (Module* m : internal->modules) { |
|
|
|
@@ -809,14 +657,31 @@ |
|
|
|
@@ -809,14 +660,31 @@ |
|
|
|
m->rightExpander.module = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -810,7 +843,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -824,7 +689,8 @@ |
|
|
|
@@ -824,7 +692,8 @@ |
|
|
|
SharedLock<SharedMutex> lock(internal->mutex); |
|
|
|
// TODO Performance could be improved by searching modulesCache, but more testing would be needed to make sure it's always valid. |
|
|
|
auto it = std::find(internal->modules.begin(), internal->modules.end(), module); |
|
|
|
@@ -820,7 +853,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -844,7 +710,7 @@ |
|
|
|
@@ -844,7 +713,7 @@ |
|
|
|
|
|
|
|
void Engine::resetModule(Module* module) { |
|
|
|
std::lock_guard<SharedMutex> lock(internal->mutex); |
|
|
|
@@ -829,7 +862,7 @@ |
|
|
|
|
|
|
|
Module::ResetEvent eReset; |
|
|
|
module->onReset(eReset); |
|
|
|
@@ -853,7 +719,7 @@ |
|
|
|
@@ -853,7 +722,7 @@ |
|
|
|
|
|
|
|
void Engine::randomizeModule(Module* module) { |
|
|
|
std::lock_guard<SharedMutex> lock(internal->mutex); |
|
|
|
@@ -838,7 +871,7 @@ |
|
|
|
|
|
|
|
Module::RandomizeEvent eRandomize; |
|
|
|
module->onRandomize(eRandomize); |
|
|
|
@@ -861,7 +727,7 @@ |
|
|
|
@@ -861,7 +730,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
void Engine::bypassModule(Module* module, bool bypassed) { |
|
|
|
@@ -847,7 +880,7 @@ |
|
|
|
if (module->isBypassed() == bypassed) |
|
|
|
return; |
|
|
|
|
|
|
|
@@ -912,6 +778,10 @@ |
|
|
|
@@ -912,6 +781,10 @@ |
|
|
|
Module::SaveEvent e; |
|
|
|
module->onSave(e); |
|
|
|
} |
|
|
|
@@ -858,7 +891,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -946,16 +816,16 @@ |
|
|
|
@@ -946,16 +819,16 @@ |
|
|
|
|
|
|
|
void Engine::addCable(Cable* cable) { |
|
|
|
std::lock_guard<SharedMutex> lock(internal->mutex); |
|
|
|
@@ -880,7 +913,7 @@ |
|
|
|
// Get connected status of output, to decide whether we need to call a PortChangeEvent. |
|
|
|
// It's best to not trust `cable->outputModule->outputs[cable->outputId]->isConnected()` |
|
|
|
if (cable2->outputModule == cable->outputModule && cable2->outputId == cable->outputId) |
|
|
|
@@ -969,6 +839,8 @@ |
|
|
|
@@ -969,6 +842,8 @@ |
|
|
|
// Add the cable |
|
|
|
internal->cables.push_back(cable); |
|
|
|
internal->cablesCache[cable->id] = cable; |
|
|
|
@@ -889,7 +922,7 @@ |
|
|
|
Engine_updateConnected(this); |
|
|
|
// Dispatch input port event |
|
|
|
{ |
|
|
|
@@ -996,10 +868,12 @@ |
|
|
|
@@ -996,10 +871,12 @@ |
|
|
|
|
|
|
|
|
|
|
|
void Engine::removeCable_NoLock(Cable* cable) { |
|
|
|
@@ -904,7 +937,7 @@ |
|
|
|
// Remove the cable |
|
|
|
internal->cablesCache.erase(cable->id); |
|
|
|
internal->cables.erase(it); |
|
|
|
@@ -1085,11 +959,11 @@ |
|
|
|
@@ -1085,11 +962,11 @@ |
|
|
|
std::lock_guard<SharedMutex> lock(internal->mutex); |
|
|
|
// New ParamHandles must be blank. |
|
|
|
// This means we don't have to refresh the cache. |
|
|
|
@@ -918,7 +951,7 @@ |
|
|
|
|
|
|
|
// Add it |
|
|
|
internal->paramHandles.insert(paramHandle); |
|
|
|
@@ -1106,7 +980,7 @@ |
|
|
|
@@ -1106,7 +983,7 @@ |
|
|
|
void Engine::removeParamHandle_NoLock(ParamHandle* paramHandle) { |
|
|
|
// Check that the ParamHandle is already added |
|
|
|
auto it = internal->paramHandles.find(paramHandle); |
|
|
|
@@ -927,7 +960,7 @@ |
|
|
|
|
|
|
|
// Remove it |
|
|
|
paramHandle->module = NULL; |
|
|
|
@@ -1143,7 +1017,7 @@ |
|
|
|
@@ -1143,7 +1020,7 @@ |
|
|
|
void Engine::updateParamHandle_NoLock(ParamHandle* paramHandle, int64_t moduleId, int paramId, bool overwrite) { |
|
|
|
// Check that it exists |
|
|
|
auto it = internal->paramHandles.find(paramHandle); |
|
|
|
@@ -936,7 +969,7 @@ |
|
|
|
|
|
|
|
// Set IDs |
|
|
|
paramHandle->moduleId = moduleId; |
|
|
|
@@ -1187,6 +1061,10 @@ |
|
|
|
@@ -1187,6 +1064,10 @@ |
|
|
|
json_t* moduleJ = module->toJson(); |
|
|
|
json_array_append_new(modulesJ, moduleJ); |
|
|
|
} |
|
|
|
@@ -947,7 +980,7 @@ |
|
|
|
json_object_set_new(rootJ, "modules", modulesJ); |
|
|
|
|
|
|
|
// cables |
|
|
|
@@ -1197,11 +1075,6 @@ |
|
|
|
@@ -1197,11 +1078,6 @@ |
|
|
|
} |
|
|
|
json_object_set_new(rootJ, "cables", cablesJ); |
|
|
|
|
|
|
|
@@ -959,7 +992,7 @@ |
|
|
|
return rootJ; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -1225,14 +1098,20 @@ |
|
|
|
@@ -1225,14 +1101,20 @@ |
|
|
|
} |
|
|
|
catch (Exception& e) { |
|
|
|
WARN("Cannot load model: %s", e.what()); |
|
|
|
@@ -984,7 +1017,7 @@ |
|
|
|
|
|
|
|
try { |
|
|
|
// This doesn't need a lock because the Module is not added to the Engine yet. |
|
|
|
@@ -1248,7 +1127,8 @@ |
|
|
|
@@ -1248,7 +1130,8 @@ |
|
|
|
} |
|
|
|
catch (Exception& e) { |
|
|
|
WARN("Cannot load module: %s", e.what()); |
|
|
|
@@ -994,7 +1027,7 @@ |
|
|
|
delete module; |
|
|
|
continue; |
|
|
|
} |
|
|
|
@@ -1285,67 +1165,10 @@ |
|
|
|
@@ -1285,67 +1168,10 @@ |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|