@@ -30,18 +30,18 @@ struct Engine { | |||||
void clear(); | void clear(); | ||||
INTERNAL void clear_NoLock(); | INTERNAL void clear_NoLock(); | ||||
/** Advances the engine by `frames` frames. | /** Advances the engine by `frames` frames. | ||||
Only call this method from the primary module. | |||||
Only call this method from the master module. | |||||
Read-locks. Also locks so only one stepBlock() can be called simultaneously or recursively. | Read-locks. Also locks so only one stepBlock() can be called simultaneously or recursively. | ||||
*/ | */ | ||||
void stepBlock(int frames); | void stepBlock(int frames); | ||||
/** Module does not need to belong to the Engine. | /** Module does not need to belong to the Engine. | ||||
However, Engine will unset the primary module when it is removed from the Engine. | |||||
NULL will unset the primary module. | |||||
However, Engine will unset the master module when it is removed from the Engine. | |||||
NULL will unset the master module. | |||||
Write-locks. | Write-locks. | ||||
*/ | */ | ||||
void setPrimaryModule(Module* module); | |||||
INTERNAL void setPrimaryModule_NoLock(Module* module); | |||||
Module* getPrimaryModule(); | |||||
void setMasterModule(Module* module); | |||||
INTERNAL void setMasterModule_NoLock(Module* module); | |||||
Module* getMasterModule(); | |||||
/** Returns the sample rate used by the engine for stepping each module. | /** Returns the sample rate used by the engine for stepping each module. | ||||
*/ | */ | ||||
@@ -225,7 +225,7 @@ struct Engine { | |||||
*/ | */ | ||||
void fromJson(json_t* rootJ); | void fromJson(json_t* rootJ); | ||||
/** If no primary module is set, the fallback Engine thread will step blocks, using the CPU clock for timing. | |||||
/** If no master module is set, the fallback Engine thread will step blocks, using the CPU clock for timing. | |||||
*/ | */ | ||||
void startFallbackThread(); | void startFallbackThread(); | ||||
}; | }; | ||||
@@ -410,11 +410,11 @@ struct Module { | |||||
*/ | */ | ||||
virtual void onSave(const SaveEvent& e) {} | virtual void onSave(const SaveEvent& e) {} | ||||
struct SetPrimaryEvent {}; | |||||
virtual void onSetPrimary(const SetPrimaryEvent& e) {} | |||||
struct SetMasterEvent {}; | |||||
virtual void onSetMaster(const SetMasterEvent& e) {} | |||||
struct UnsetPrimaryEvent {}; | |||||
virtual void onUnsetPrimary(const UnsetPrimaryEvent& e) {} | |||||
struct UnsetMasterEvent {}; | |||||
virtual void onUnsetMaster(const UnsetMasterEvent& e) {} | |||||
/** DEPRECATED. Override `onAdd(e)` instead. */ | /** DEPRECATED. Override `onAdd(e)` instead. */ | ||||
virtual void onAdd() {} | virtual void onAdd() {} | ||||
@@ -36,24 +36,24 @@ struct AudioInterfacePort : audio::Port { | |||||
outputSrc.setQuality(6); | outputSrc.setQuality(6); | ||||
} | } | ||||
void setPrimary() { | |||||
APP->engine->setPrimaryModule(module); | |||||
void setMaster() { | |||||
APP->engine->setMasterModule(module); | |||||
} | } | ||||
bool isPrimary() { | |||||
return APP->engine->getPrimaryModule() == module; | |||||
bool isMaster() { | |||||
return APP->engine->getMasterModule() == module; | |||||
} | } | ||||
void processInput(const float* input, int inputStride, int frames) override { | void processInput(const float* input, int inputStride, int frames) override { | ||||
// DEBUG("%p: new device block ____________________________", this); | // DEBUG("%p: new device block ____________________________", this); | ||||
// Claim primary module if there is none | |||||
if (!APP->engine->getPrimaryModule()) { | |||||
setPrimary(); | |||||
// Claim master module if there is none | |||||
if (!APP->engine->getMasterModule()) { | |||||
setMaster(); | |||||
} | } | ||||
bool isPrimaryCached = isPrimary(); | |||||
bool isMasterCached = isMaster(); | |||||
// Set sample rate of engine if engine sample rate is "auto". | // Set sample rate of engine if engine sample rate is "auto". | ||||
if (isPrimaryCached) { | |||||
if (isMasterCached) { | |||||
APP->engine->setSuggestedSampleRate(deviceSampleRate); | APP->engine->setSuggestedSampleRate(deviceSampleRate); | ||||
} | } | ||||
@@ -64,15 +64,15 @@ struct AudioInterfacePort : audio::Port { | |||||
// Consider engine buffers "too full" if they contain a bit more than the audio device's number of frames, converted to engine sample rate. | // Consider engine buffers "too full" if they contain a bit more than the audio device's number of frames, converted to engine sample rate. | ||||
int maxEngineFrames = (int) std::ceil(frames * sampleRateRatio * 2.0) - 1; | int maxEngineFrames = (int) std::ceil(frames * sampleRateRatio * 2.0) - 1; | ||||
// If the engine output buffer is too full, clear it to keep latency low. No need to clear if primary because it's always cleared below. | |||||
if (!isPrimaryCached && (int) engineOutputBuffer.size() > maxEngineFrames) { | |||||
// If the engine output buffer is too full, clear it to keep latency low. No need to clear if master because it's always cleared below. | |||||
if (!isMasterCached && (int) engineOutputBuffer.size() > maxEngineFrames) { | |||||
engineOutputBuffer.clear(); | engineOutputBuffer.clear(); | ||||
// DEBUG("%p: clearing engine output", this); | // DEBUG("%p: clearing engine output", this); | ||||
} | } | ||||
if (deviceNumInputs > 0) { | if (deviceNumInputs > 0) { | ||||
// Always clear engine output if primary | |||||
if (isPrimaryCached) { | |||||
// Always clear engine output if master | |||||
if (isMasterCached) { | |||||
engineOutputBuffer.clear(); | engineOutputBuffer.clear(); | ||||
} | } | ||||
// Set up sample rate converter | // Set up sample rate converter | ||||
@@ -102,14 +102,14 @@ struct AudioInterfacePort : audio::Port { | |||||
void processBuffer(const float* input, int inputStride, float* output, int outputStride, int frames) override { | void processBuffer(const float* input, int inputStride, float* output, int outputStride, int frames) override { | ||||
// Step engine | // Step engine | ||||
if (isPrimary() && requestedEngineFrames > 0) { | |||||
if (isMaster() && requestedEngineFrames > 0) { | |||||
// DEBUG("%p: %d block, stepping %d", this, frames, requestedEngineFrames); | // DEBUG("%p: %d block, stepping %d", this, frames, requestedEngineFrames); | ||||
APP->engine->stepBlock(requestedEngineFrames); | APP->engine->stepBlock(requestedEngineFrames); | ||||
} | } | ||||
} | } | ||||
void processOutput(float* output, int outputStride, int frames) override { | void processOutput(float* output, int outputStride, int frames) override { | ||||
// bool isPrimaryCached = isPrimary(); | |||||
// bool isMasterCached = isMaster(); | |||||
float engineSampleRate = APP->engine->getSampleRate(); | float engineSampleRate = APP->engine->getSampleRate(); | ||||
float sampleRateRatio = engineSampleRate / deviceSampleRate; | float sampleRateRatio = engineSampleRate / deviceSampleRate; | ||||
@@ -148,7 +148,7 @@ struct AudioInterfacePort : audio::Port { | |||||
// DEBUG("%p: clearing engine input", this); | // DEBUG("%p: clearing engine input", this); | ||||
} | } | ||||
// DEBUG("%p %s:\tframes %d requestedEngineFrames %d\toutputBuffer %d engineInputBuffer %d\t", this, isPrimaryCached ? "primary" : "secondary", frames, requestedEngineFrames, engineOutputBuffer.size(), engineInputBuffer.size()); | |||||
// DEBUG("%p %s:\tframes %d requestedEngineFrames %d\toutputBuffer %d engineInputBuffer %d\t", this, isMasterCached ? "master" : "secondary", frames, requestedEngineFrames, engineOutputBuffer.size(), engineInputBuffer.size()); | |||||
} | } | ||||
void onStartStream() override { | void onStartStream() override { | ||||
@@ -388,12 +388,12 @@ struct AudioInterface : Module { | |||||
/** Must be called when the Engine mutex is unlocked. | /** Must be called when the Engine mutex is unlocked. | ||||
*/ | */ | ||||
void setPrimary() { | |||||
APP->engine->setPrimaryModule(this); | |||||
void setMaster() { | |||||
APP->engine->setMasterModule(this); | |||||
} | } | ||||
bool isPrimary() { | |||||
return APP->engine->getPrimaryModule() == this; | |||||
bool isMaster() { | |||||
return APP->engine->getMasterModule() == this; | |||||
} | } | ||||
}; | }; | ||||
@@ -561,9 +561,9 @@ struct AudioInterfaceWidget : ModuleWidget { | |||||
menu->addChild(new MenuSeparator); | menu->addChild(new MenuSeparator); | ||||
menu->addChild(createCheckMenuItem("Primary audio module", | |||||
[=]() {return module->isPrimary();}, | |||||
[=]() {module->setPrimary();} | |||||
menu->addChild(createCheckMenuItem("Master audio module", | |||||
[=]() {return module->isMaster();}, | |||||
[=]() {module->setMaster();} | |||||
)); | )); | ||||
menu->addChild(createBoolPtrMenuItem("DC blocker", &module->dcFilterEnabled)); | menu->addChild(createBoolPtrMenuItem("DC blocker", &module->dcFilterEnabled)); | ||||
@@ -235,7 +235,7 @@ struct Engine::Internal { | |||||
std::vector<Module*> modules; | std::vector<Module*> modules; | ||||
std::vector<Cable*> cables; | std::vector<Cable*> cables; | ||||
std::set<ParamHandle*> paramHandles; | std::set<ParamHandle*> paramHandles; | ||||
Module* primaryModule = NULL; | |||||
Module* masterModule = NULL; | |||||
// moduleId | // moduleId | ||||
std::map<int64_t, Module*> modulesCache; | std::map<int64_t, Module*> modulesCache; | ||||
@@ -631,41 +631,41 @@ void Engine::stepBlock(int frames) { | |||||
} | } | ||||
void Engine::setPrimaryModule(Module* module) { | |||||
if (module == internal->primaryModule) | |||||
void Engine::setMasterModule(Module* module) { | |||||
if (module == internal->masterModule) | |||||
return; | return; | ||||
WriteLock lock(internal->mutex); | WriteLock lock(internal->mutex); | ||||
setPrimaryModule_NoLock(module); | |||||
setMasterModule_NoLock(module); | |||||
} | } | ||||
void Engine::setPrimaryModule_NoLock(Module* module) { | |||||
if (module == internal->primaryModule) | |||||
void Engine::setMasterModule_NoLock(Module* module) { | |||||
if (module == internal->masterModule) | |||||
return; | return; | ||||
if (internal->primaryModule) { | |||||
// Dispatch UnsetPrimaryEvent | |||||
Module::UnsetPrimaryEvent e; | |||||
internal->primaryModule->onUnsetPrimary(e); | |||||
if (internal->masterModule) { | |||||
// Dispatch UnsetMasterEvent | |||||
Module::UnsetMasterEvent e; | |||||
internal->masterModule->onUnsetMaster(e); | |||||
} | } | ||||
internal->primaryModule = module; | |||||
internal->masterModule = module; | |||||
if (internal->primaryModule) { | |||||
// Dispatch SetPrimaryEvent | |||||
Module::SetPrimaryEvent e; | |||||
internal->primaryModule->onSetPrimary(e); | |||||
if (internal->masterModule) { | |||||
// Dispatch SetMasterEvent | |||||
Module::SetMasterEvent e; | |||||
internal->masterModule->onSetMaster(e); | |||||
} | } | ||||
// Wake up fallback thread if primary module was unset | |||||
if (!internal->primaryModule) { | |||||
// Wake up fallback thread if master module was unset | |||||
if (!internal->masterModule) { | |||||
internal->fallbackCv.notify_all(); | internal->fallbackCv.notify_all(); | ||||
} | } | ||||
} | } | ||||
Module* Engine::getPrimaryModule() { | |||||
return internal->primaryModule; | |||||
Module* Engine::getMasterModule() { | |||||
return internal->masterModule; | |||||
} | } | ||||
@@ -833,9 +833,9 @@ void Engine::removeModule_NoLock(Module* module) { | |||||
if (paramHandle->moduleId == module->id) | if (paramHandle->moduleId == module->id) | ||||
paramHandle->module = NULL; | paramHandle->module = NULL; | ||||
} | } | ||||
// Unset primary module | |||||
if (getPrimaryModule() == module) { | |||||
setPrimaryModule_NoLock(NULL); | |||||
// Unset master module | |||||
if (getMasterModule() == module) { | |||||
setMasterModule_NoLock(NULL); | |||||
} | } | ||||
// If a param is being smoothed on this module, stop smoothing it immediately | // If a param is being smoothed on this module, stop smoothing it immediately | ||||
if (module == internal->smoothModule) { | if (module == internal->smoothModule) { | ||||
@@ -1225,9 +1225,9 @@ json_t* Engine::toJson() { | |||||
} | } | ||||
json_object_set_new(rootJ, "cables", cablesJ); | json_object_set_new(rootJ, "cables", cablesJ); | ||||
// primaryModule | |||||
if (internal->primaryModule) { | |||||
json_object_set_new(rootJ, "primaryModuleId", json_integer(internal->primaryModule->id)); | |||||
// masterModule | |||||
if (internal->masterModule) { | |||||
json_object_set_new(rootJ, "masterModuleId", json_integer(internal->masterModule->id)); | |||||
} | } | ||||
return rootJ; | return rootJ; | ||||
@@ -1313,11 +1313,11 @@ void Engine::fromJson(json_t* rootJ) { | |||||
} | } | ||||
} | } | ||||
// primaryModule | |||||
json_t* primaryModuleIdJ = json_object_get(rootJ, "primaryModuleId"); | |||||
if (primaryModuleIdJ) { | |||||
Module* primaryModule = getModule(json_integer_value(primaryModuleIdJ)); | |||||
setPrimaryModule(primaryModule); | |||||
// masterModule | |||||
json_t* masterModuleIdJ = json_object_get(rootJ, "masterModuleId"); | |||||
if (masterModuleIdJ) { | |||||
Module* masterModule = getModule(json_integer_value(masterModuleIdJ)); | |||||
setMasterModule(masterModule); | |||||
} | } | ||||
} | } | ||||
@@ -1344,7 +1344,7 @@ static void Engine_fallbackRun(Engine* that) { | |||||
contextSet(that->internal->context); | contextSet(that->internal->context); | ||||
while (that->internal->fallbackRunning) { | while (that->internal->fallbackRunning) { | ||||
if (!that->getPrimaryModule()) { | |||||
if (!that->getMasterModule()) { | |||||
// Step blocks and wait | // Step blocks and wait | ||||
double start = system::getTime(); | double start = system::getTime(); | ||||
int frames = std::floor(that->getSampleRate() / 60); | int frames = std::floor(that->getSampleRate() / 60); | ||||
@@ -1357,10 +1357,10 @@ static void Engine_fallbackRun(Engine* that) { | |||||
} | } | ||||
} | } | ||||
else { | else { | ||||
// Wait for primary module to be unset, or for the request to stop running | |||||
// Wait for master module to be unset, or for the request to stop running | |||||
std::unique_lock<std::mutex> lock(that->internal->fallbackMutex); | std::unique_lock<std::mutex> lock(that->internal->fallbackMutex); | ||||
that->internal->fallbackCv.wait(lock, [&]() { | that->internal->fallbackCv.wait(lock, [&]() { | ||||
return !that->internal->fallbackRunning || !that->getPrimaryModule(); | |||||
return !that->internal->fallbackRunning || !that->getMasterModule(); | |||||
}); | }); | ||||
} | } | ||||
} | } | ||||