| @@ -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(); | |||
| }); | |||
| } | |||
| } | |||