BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

commit b68a62b1aff07f0df9fb8afb5d63925c715b79f4
parent 0b0674f23cce47c5e00052305452c577f6b4a895
Author: Matt Demanett <matt@demanett.net>
Date:   Sun,  7 Jan 2018 22:22:52 -0500

DGate: auto-loop-on-patch-load behavior.  Idea here is that if the module is looping when the patch is saved, then it should resume looping, without a trigger, when the patch loads.  A context menu exposes a persistent setting per-module, defaulting to on, which allows toggling back to the old behavior, where a trigger was required after patch load to start the loop.  This same behavior remains to be cloned to Shaper[+] and DADSRH[+].

Diffstat:
Msrc/BogaudioModules.hpp | 1+
Msrc/DGate.cpp | 54+++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/src/BogaudioModules.hpp b/src/BogaudioModules.hpp @@ -39,6 +39,7 @@ struct AnalyzerWidget : ModuleWidget { struct DGateWidget : ModuleWidget { DGateWidget(); + virtual Menu* createContextMenu() override; }; struct OffsetWidget : ModuleWidget { diff --git a/src/DGate.cpp b/src/DGate.cpp @@ -33,6 +33,9 @@ struct DGate : Module { GATE_STAGE }; + bool _firstStep = true; + bool _loopOnLoad = true; + bool _shouldLoopOnLoad = true; SchmittTrigger _trigger; PulseGenerator _triggerOuptutPulseGen; Stage _stage; @@ -42,11 +45,31 @@ struct DGate : Module { reset(); } + virtual json_t* toJson() override; + virtual void fromJson(json_t* root) override; virtual void reset() override; virtual void step() override; bool stepStage(Param& knob); }; +json_t* DGate::toJson() { + json_t* root = json_object(); + json_object_set_new(root, "loopOnLoad", json_boolean(_loopOnLoad)); + json_object_set_new(root, "shouldLoopOnLoad", json_boolean(_stage != STOPPED_STAGE)); + return root; +} + +void DGate::fromJson(json_t* root) { + json_t* loopOnLoad = json_object_get(root, "loopOnLoad"); + if (loopOnLoad) { + _loopOnLoad = json_is_true(loopOnLoad); + } + json_t* shouldLoopOnLoad = json_object_get(root, "shouldLoopOnLoad"); + if (shouldLoopOnLoad) { + _shouldLoopOnLoad = json_is_true(shouldLoopOnLoad); + } +} + void DGate::reset() { _trigger.reset(); _triggerOuptutPulseGen.process(10.0); @@ -57,7 +80,10 @@ void DGate::reset() { void DGate::step() { float envelope = 0.0; bool complete = false; - if (_trigger.process(params[TRIGGER_PARAM].value + inputs[TRIGGER_INPUT].value)) { + if ( + _trigger.process(params[TRIGGER_PARAM].value + inputs[TRIGGER_INPUT].value) || + (_firstStep && _loopOnLoad && _shouldLoopOnLoad && params[LOOP_PARAM].value <= 0.0) + ) { _stage = DELAY_STAGE; _stageProgress = 0.0; } @@ -100,6 +126,8 @@ void DGate::step() { lights[DELAY_LIGHT].value = _stage == DELAY_STAGE; lights[GATE_LIGHT].value = _stage == GATE_STAGE; + + _firstStep = false; } bool DGate::stepStage(Param& knob) { @@ -155,3 +183,27 @@ DGateWidget::DGateWidget() { addChild(createLight<TinyLight<GreenLight>>(delayLightPosition, module, DGate::DELAY_LIGHT)); addChild(createLight<TinyLight<GreenLight>>(gateLightPosition, module, DGate::GATE_LIGHT)); } + +struct DGateWidgetAutoloopMenuItem : MenuItem { + DGate* _module; + DGateWidgetAutoloopMenuItem(DGate* module, const char* label) : _module(module) { + this->text = label; + } + + void onAction(EventAction &e) override { + _module->_loopOnLoad = !_module->_loopOnLoad; + } + + void step() override { + rightText = _module->_loopOnLoad ? "✔" : ""; + } +}; + +Menu* DGateWidget::createContextMenu() { + DGate* dgate = dynamic_cast<DGate*>(module); + assert(dgate); + Menu* menu = ModuleWidget::createContextMenu(); + menu->addChild(new MenuLabel()); + menu->addChild(new DGateWidgetAutoloopMenuItem(dgate, "Loop on Patch Load")); + return menu; +}