@@ -30,18 +30,18 @@ struct Engine { | |||
void clear(); | |||
INTERNAL void clear_NoLock(); | |||
/** 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. | |||
*/ | |||
void stepBlock(int frames); | |||
/** 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. | |||
*/ | |||
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. | |||
*/ | |||
@@ -225,7 +225,7 @@ struct Engine { | |||
*/ | |||
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(); | |||
}; | |||
@@ -410,11 +410,11 @@ struct Module { | |||
*/ | |||
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. */ | |||
virtual void onAdd() {} | |||
@@ -36,24 +36,24 @@ struct AudioInterfacePort : audio::Port { | |||
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 { | |||
// 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". | |||
if (isPrimaryCached) { | |||
if (isMasterCached) { | |||
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. | |||
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(); | |||
// DEBUG("%p: clearing engine output", this); | |||
} | |||
if (deviceNumInputs > 0) { | |||
// Always clear engine output if primary | |||
if (isPrimaryCached) { | |||
// Always clear engine output if master | |||
if (isMasterCached) { | |||
engineOutputBuffer.clear(); | |||
} | |||
// 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 { | |||
// Step engine | |||
if (isPrimary() && requestedEngineFrames > 0) { | |||
if (isMaster() && requestedEngineFrames > 0) { | |||
// DEBUG("%p: %d block, stepping %d", this, frames, requestedEngineFrames); | |||
APP->engine->stepBlock(requestedEngineFrames); | |||
} | |||
} | |||
void processOutput(float* output, int outputStride, int frames) override { | |||
// bool isPrimaryCached = isPrimary(); | |||
// bool isMasterCached = isMaster(); | |||
float engineSampleRate = APP->engine->getSampleRate(); | |||
float sampleRateRatio = engineSampleRate / deviceSampleRate; | |||
@@ -148,7 +148,7 @@ struct AudioInterfacePort : audio::Port { | |||
// 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 { | |||
@@ -388,12 +388,12 @@ struct AudioInterface : Module { | |||
/** 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(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)); | |||
@@ -235,7 +235,7 @@ struct Engine::Internal { | |||
std::vector<Module*> modules; | |||
std::vector<Cable*> cables; | |||
std::set<ParamHandle*> paramHandles; | |||
Module* primaryModule = NULL; | |||
Module* masterModule = NULL; | |||
// moduleId | |||
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; | |||
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; | |||
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(); | |||
} | |||
} | |||
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) | |||
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 (module == internal->smoothModule) { | |||
@@ -1225,9 +1225,9 @@ json_t* Engine::toJson() { | |||
} | |||
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; | |||
@@ -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); | |||
while (that->internal->fallbackRunning) { | |||
if (!that->getPrimaryModule()) { | |||
if (!that->getMasterModule()) { | |||
// Step blocks and wait | |||
double start = system::getTime(); | |||
int frames = std::floor(that->getSampleRate() / 60); | |||
@@ -1357,10 +1357,10 @@ static void Engine_fallbackRun(Engine* that) { | |||
} | |||
} | |||
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); | |||
that->internal->fallbackCv.wait(lock, [&]() { | |||
return !that->internal->fallbackRunning || !that->getPrimaryModule(); | |||
return !that->internal->fallbackRunning || !that->getMasterModule(); | |||
}); | |||
} | |||
} | |||