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:
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;
+}