diff --git a/Makefile b/Makefile index d449e59..01f717a 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,14 @@ -# this flag selects the rack version to compile against. -# -# possible values are v040 v_050_dev +SLUG = dekstop +VERSION = 0.6.0dev -# FLAGS += -D v040 -FLAGS += -D v_050_dev +RACK_DIR ?= ../.. + +FLAGS += -Iportaudio +LDFLAGS += -lsamplerate SOURCES = $(wildcard src/*.cpp portaudio/*.c) -include ../../plugin.mk +include $(RACK_DIR)/plugin.mk -FLAGS += -Iportaudio +DISTRIBUTABLES += $(wildcard LICENSE*) res -dist: all - mkdir -p dist/dekstop - cp LICENSE* dist/dekstop/ - cp plugin.* dist/dekstop/ - cp -R res dist/dekstop/ diff --git a/src/GateSeq8.cpp b/src/GateSeq8.cpp index e12810c..4fb4b5b 100644 --- a/src/GateSeq8.cpp +++ b/src/GateSeq8.cpp @@ -6,7 +6,7 @@ const int NUM_CHANNELS = 8; const int NUM_GATES = NUM_STEPS * NUM_CHANNELS; struct GateSEQ8 : Module { - + enum ParamIds { CLOCK_PARAM, RUN_PARAM, @@ -45,9 +45,9 @@ struct GateSEQ8 : Module { float stepLights[NUM_GATES] = {}; GateSEQ8() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} - void step(); + void step() override; - json_t *toJson() { + json_t *toJson() override { json_t *rootJ = json_object(); // Clock multiplier @@ -65,7 +65,7 @@ struct GateSEQ8 : Module { return rootJ; } - void fromJson(json_t *rootJ) { + void fromJson(json_t *rootJ) override { // Clock multiplier json_t *multiplierJ = json_object_get(rootJ, "multiplier"); if (!multiplierJ) { @@ -82,24 +82,22 @@ struct GateSEQ8 : Module { } } - void reset() { + void reset() override { for (int i = 0; i < NUM_GATES; i++) { gateState[i] = false; } } - void randomize() { + void randomize() override { for (int i = 0; i < NUM_GATES; i++) { - gateState[i] = (randomf() > 0.5); + gateState[i] = (randomUniform() > 0.5); } } }; void GateSEQ8::step() { - #ifdef v_050_dev float gSampleRate = engineGetSampleRate(); - #endif const float lightLambda = 0.1; // Run if (runningTrigger.process(params[RUN_PARAM].value)) { @@ -139,7 +137,7 @@ void GateSEQ8::step() { if (nextStep) { // Advance step - int numSteps = clampi(roundf(params[STEPS_PARAM].value + inputs[STEPS_INPUT].value), 1, NUM_STEPS); + int numSteps = clamp(static_cast(roundf(params[STEPS_PARAM].value + inputs[STEPS_INPUT].value)), 1, NUM_STEPS); index += 1; if (index >= numSteps) { index = 0; @@ -181,10 +179,10 @@ struct ClockMultiplierChoice : ChoiceButton { menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)); menu->box.size.x = box.size.x; - const float multipliers[12] = {0.25, 0.3, 0.5, 0.75, + const float multipliers[12] = {0.25, 0.3, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0}; - const std::string labels[12] = {"1/4", "1/3", "1/2", "3/4", + const std::string labels[12] = {"1/4", "1/3", "1/2", "3/4", "1/1", "3/2", "2/1", "3/1", "4/1", "6/1", "8/1", "12/1"}; int multipliersLen = sizeof(multipliers) / sizeof(multipliers[0]); @@ -201,9 +199,12 @@ struct ClockMultiplierChoice : ChoiceButton { } }; -GateSEQ8Widget::GateSEQ8Widget() { - GateSEQ8 *module = new GateSEQ8(); - setModule(module); + +struct GateSEQ8Widget : ModuleWidget { + GateSEQ8Widget(GateSEQ8 *module); +}; + +GateSEQ8Widget::GateSEQ8Widget(GateSEQ8 *module) : ModuleWidget(module) { box.size = Vec(360, 380); { @@ -213,23 +214,23 @@ GateSEQ8Widget::GateSEQ8Widget() { addChild(panel); } - addChild(createScrew(Vec(15, 0))); - addChild(createScrew(Vec(box.size.x-30, 0))); - addChild(createScrew(Vec(15, 365))); - addChild(createScrew(Vec(box.size.x-30, 365))); + addChild(Widget::create(Vec(15, 0))); + addChild(Widget::create(Vec(box.size.x-30, 0))); + addChild(Widget::create(Vec(15, 365))); + addChild(Widget::create(Vec(box.size.x-30, 365))); - addParam(createParam(Vec(17, 56), module, GateSEQ8::CLOCK_PARAM, -2.0, 10.0, 2.0)); - addParam(createParam(Vec(60, 61-1), module, GateSEQ8::RUN_PARAM, 0.0, 1.0, 0.0)); - addChild(createLight>(Vec(60+6, 61+5), module, GateSEQ8::RUNNING_LIGHT)); - addParam(createParam(Vec(98, 61-1), module, GateSEQ8::RESET_PARAM, 0.0, 1.0, 0.0)); - addChild(createLight>(Vec(98+6, 61+5), module, GateSEQ8::RESET_LIGHT)); - addParam(createParam(Vec(132, 56), module, GateSEQ8::STEPS_PARAM, 1.0, NUM_STEPS, NUM_STEPS)); + addParam(ParamWidget::create(Vec(17, 56), module, GateSEQ8::CLOCK_PARAM, -2.0, 10.0, 2.0)); + addParam(ParamWidget::create(Vec(60, 61-1), module, GateSEQ8::RUN_PARAM, 0.0, 1.0, 0.0)); + addChild(ModuleLightWidget::create>(Vec(60+6, 61+5), module, GateSEQ8::RUNNING_LIGHT)); + addParam(ParamWidget::create(Vec(98, 61-1), module, GateSEQ8::RESET_PARAM, 0.0, 1.0, 0.0)); + addChild(ModuleLightWidget::create>(Vec(98+6, 61+5), module, GateSEQ8::RESET_LIGHT)); + addParam(ParamWidget::create(Vec(132, 56), module, GateSEQ8::STEPS_PARAM, 1.0, NUM_STEPS, NUM_STEPS)); static const float portX[8] = {19, 57, 96, 134, 173, 211, 250, 288}; - addInput(createInput(Vec(portX[0]-1, 99-1), module, GateSEQ8::CLOCK_INPUT)); - addInput(createInput(Vec(portX[1]-1, 99-1), module, GateSEQ8::EXT_CLOCK_INPUT)); - addInput(createInput(Vec(portX[2]-1, 99-1), module, GateSEQ8::RESET_INPUT)); - addInput(createInput(Vec(portX[3]-1, 99-1), module, GateSEQ8::STEPS_INPUT)); + addInput(Port::create(Vec(portX[0]-1, 99-1), Port::INPUT, module, GateSEQ8::CLOCK_INPUT)); + addInput(Port::create(Vec(portX[1]-1, 99-1), Port::INPUT, module, GateSEQ8::EXT_CLOCK_INPUT)); + addInput(Port::create(Vec(portX[2]-1, 99-1), Port::INPUT, module, GateSEQ8::RESET_INPUT)); + addInput(Port::create(Vec(portX[3]-1, 99-1), Port::INPUT, module, GateSEQ8::STEPS_INPUT)); { Label *label = new Label(); @@ -247,9 +248,11 @@ GateSEQ8Widget::GateSEQ8Widget() { for (int y = 0; y < NUM_CHANNELS; y++) { for (int x = 0; x < NUM_STEPS; x++) { int i = y*NUM_STEPS+x; - addParam(createParam(Vec(22 + x*25, 155+y*25+3), module, GateSEQ8::GATE1_PARAM + i, 0.0, 1.0, 0.0)); - addChild(createLight>(Vec(28 + x*25, 156+y*25+8), module, GateSEQ8::GATE_LIGHTS + i)); + addParam(ParamWidget::create(Vec(22 + x*25, 155+y*25+3), module, GateSEQ8::GATE1_PARAM + i, 0.0, 1.0, 0.0)); + addChild(ModuleLightWidget::create>(Vec(28 + x*25, 156+y*25+8), module, GateSEQ8::GATE_LIGHTS + i)); } - addOutput(createOutput(Vec(320, 155+y*25), module, GateSEQ8::GATE1_OUTPUT + y)); + addOutput(Port::create(Vec(320, 155+y*25), Port::OUTPUT, module, GateSEQ8::GATE1_OUTPUT + y)); } } + +Model *modelGateSEQ8 = Model::create("dekstop", "GateSEQ8", "Gate SEQ-8", SEQUENCER_TAG); diff --git a/src/Recorder.cpp b/src/Recorder.cpp index f7ac3ed..0b5f52e 100644 --- a/src/Recorder.cpp +++ b/src/Recorder.cpp @@ -30,7 +30,7 @@ struct Recorder : Module { RECORDING_LIGHT, NUM_LIGHTS }; - + std::string filename; WAV_Writer writer; std::atomic_bool isRecording; @@ -45,7 +45,7 @@ struct Recorder : Module { isRecording = false; } ~Recorder(); - void step(); + void step() override; void clear(); void startRecording(); void stopRecording(); @@ -96,9 +96,7 @@ void Recorder::saveAsDialog() { template void Recorder::openWAV() { - #ifdef v_050_dev float gSampleRate = engineGetSampleRate(); - #endif if (!filename.empty()) { fprintf(stdout, "Recording to %s\n", filename.c_str()); int result = Audio_WAV_OpenWriter(&writer, filename.c_str(), gSampleRate, ChannelCount); @@ -108,7 +106,7 @@ void Recorder::openWAV() { snprintf(msg, sizeof(msg), "Failed to open WAV file, result = %d\n", result); osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, msg); fprintf(stderr, "%s", msg); - } + } } } @@ -128,9 +126,7 @@ void Recorder::closeWAV() { // Run in a separate thread template void Recorder::recorderRun() { - #ifdef v_050_dev float gSampleRate = engineGetSampleRate(); - #endif while (isRecording) { // Wake up a few times a second, often enough to never overflow the buffer. float sleepTime = (1.0 * BUFFERSIZE / gSampleRate) / 2.0; @@ -184,7 +180,7 @@ struct RecordButton : LEDButton { Callback onPressCallback; SchmittTrigger recordTrigger; - + void onChange(EventChange &e) override { if (recordTrigger.process(value)) { onPress(e); @@ -196,11 +192,16 @@ struct RecordButton : LEDButton { } }; +template +struct RecorderWidget : ModuleWidget { + RecorderWidget(Recorder *module); + json_t *toJsonData(); + void fromJsonData(json_t *root); +}; + template -RecorderWidget::RecorderWidget() { - Recorder *module = new Recorder(); - setModule(module); +RecorderWidget::RecorderWidget(Recorder *module) : ModuleWidget(module) { box.size = Vec(15*6+5, 380); { @@ -223,7 +224,7 @@ RecorderWidget::RecorderWidget() { xPos = 35; yPos += 2*margin; - ParamWidget *recordButton = createParam(Vec(xPos, yPos-1), module, Recorder::RECORD_PARAM, 0.0, 1.0, 0.0); + ParamWidget *recordButton = ParamWidget::create(Vec(xPos, yPos-1), module, Recorder::RECORD_PARAM, 0.0, 1.0, 0.0); RecordButton *btn = dynamic_cast(recordButton); Recorder *recorder = dynamic_cast*>(module); @@ -236,7 +237,7 @@ RecorderWidget::RecorderWidget() { } }; addParam(recordButton); - addChild(createLight>(Vec(xPos+6, yPos+5), module, Recorder::RECORDING_LIGHT)); + addChild(ModuleLightWidget::create>(Vec(xPos+6, yPos+5), module, Recorder::RECORDING_LIGHT)); xPos = margin; yPos += recordButton->box.size.y + 3*margin; } @@ -252,7 +253,7 @@ RecorderWidget::RecorderWidget() { yPos += 5; xPos = 10; for (unsigned int i = 0; i < ChannelCount; i++) { - addInput(createInput(Vec(xPos, yPos), module, i)); + addInput(Port::create(Vec(xPos, yPos), Port::INPUT, module, i)); Label *label = new Label(); label->box.pos = Vec(xPos + 4, yPos + 28); label->text = stringf("%d", i + 1); @@ -267,12 +268,5 @@ RecorderWidget::RecorderWidget() { } } -Recorder2Widget::Recorder2Widget() : - RecorderWidget<2u>() -{ -} - -Recorder8Widget::Recorder8Widget() : - RecorderWidget<8u>() -{ -} +Model *modelRecorder2 = Model::create, RecorderWidget<2>>("dekstop", "Recorder2", "Recorder 2", UTILITY_TAG); +Model *modelRecorder8 = Model::create, RecorderWidget<8>>("dekstop", "Recorder8", "Recorder 8", UTILITY_TAG); diff --git a/src/TriSEQ3.cpp b/src/TriSEQ3.cpp index 67c71f9..616f778 100644 --- a/src/TriSEQ3.cpp +++ b/src/TriSEQ3.cpp @@ -48,9 +48,9 @@ struct TriSEQ3 : Module { float stepLights[8] = {}; TriSEQ3() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} - void step(); + void step() override; - json_t *toJson() { + json_t *toJson() override { json_t *rootJ = json_object(); json_t *gatesJ = json_array(); @@ -63,7 +63,7 @@ struct TriSEQ3 : Module { return rootJ; } - void fromJson(json_t *rootJ) { + void fromJson(json_t *rootJ) override { json_t *gatesJ = json_object_get(rootJ, "gates"); for (int i = 0; i < 8; i++) { json_t *gateJ = json_array_get(gatesJ, i); @@ -71,28 +71,22 @@ struct TriSEQ3 : Module { } } -#ifdef v_050_dev - void reset() { -#else - void initialize() { -#endif + void reset() override { for (int i = 0; i < 8; i++) { gateState[i] = false; } } - void randomize() { + void randomize() override { for (int i = 0; i < 8; i++) { - gateState[i] = (randomf() > 0.5); + gateState[i] = (randomUniform() > 0.5); } } }; void TriSEQ3::step() { - #ifdef v_050_dev float gSampleRate = engineGetSampleRate(); - #endif const float lightLambda = 0.1; // Run if (runningTrigger.process(params[RUN_PARAM].value)) { @@ -131,7 +125,7 @@ void TriSEQ3::step() { if (nextStep) { // Advance step - int numSteps = clampi(roundf(params[STEPS_PARAM].value + inputs[STEPS_INPUT].value), 1, 8); + int numSteps = clamp(static_cast(roundf(params[STEPS_PARAM].value + inputs[STEPS_INPUT].value)), 1, 8); index += 1; if (index >= numSteps) { index = 0; @@ -167,10 +161,12 @@ void TriSEQ3::step() { lights[ROW_LIGHTS + 2].value = row3; } +struct TriSEQ3Widget : ModuleWidget { + TriSEQ3Widget(TriSEQ3 *module); +}; + -TriSEQ3Widget::TriSEQ3Widget() { - TriSEQ3 *module = new TriSEQ3(); - setModule(module); +TriSEQ3Widget::TriSEQ3Widget(TriSEQ3 *module) : ModuleWidget(module) { box.size = Vec(15*22, 380); { @@ -180,38 +176,41 @@ TriSEQ3Widget::TriSEQ3Widget() { addChild(panel); } - addChild(createScrew(Vec(15, 0))); - addChild(createScrew(Vec(box.size.x-30, 0))); - addChild(createScrew(Vec(15, 365))); - addChild(createScrew(Vec(box.size.x-30, 365))); - - addParam(createParam(Vec(17, 56), module, TriSEQ3::CLOCK_PARAM, -2.0, 10.0, 2.0)); - addParam(createParam(Vec(60, 61-1), module, TriSEQ3::RUN_PARAM, 0.0, 1.0, 0.0)); - addChild(createLight>(Vec(60+6, 61+5), module, TriSEQ3::RUNNING_LIGHT)); - addParam(createParam(Vec(98, 61-1), module, TriSEQ3::RESET_PARAM, 0.0, 1.0, 0.0)); - addChild(createLight>(Vec(98+6, 61+5), module, TriSEQ3::RESET_LIGHT)); - addParam(createParam(Vec(132, 56), module, TriSEQ3::STEPS_PARAM, 1.0, 8.0, 8.0)); - addChild(createLight>(Vec(181.5, 66), module, TriSEQ3::GATES_LIGHT)); - addChild(createLight>(Vec(219.5, 66), module, TriSEQ3::ROW_LIGHTS + 0)); - addChild(createLight>(Vec(258, 66), module, TriSEQ3::ROW_LIGHTS + 1)); - addChild(createLight>(Vec(296.5, 66), module, TriSEQ3::ROW_LIGHTS + 2)); + addChild(Widget::create(Vec(15, 0))); + addChild(Widget::create(Vec(box.size.x-30, 0))); + addChild(Widget::create(Vec(15, 365))); + addChild(Widget::create(Vec(box.size.x-30, 365))); + + addParam(ParamWidget::create(Vec(17, 56), module, TriSEQ3::CLOCK_PARAM, -2.0, 10.0, 2.0)); + addParam(ParamWidget::create(Vec(60, 61-1), module, TriSEQ3::RUN_PARAM, 0.0, 1.0, 0.0)); + addChild(ModuleLightWidget::create>(Vec(60+6, 61+5), module, TriSEQ3::RUNNING_LIGHT)); + addParam(ParamWidget::create(Vec(98, 61-1), module, TriSEQ3::RESET_PARAM, 0.0, 1.0, 0.0)); + addChild(ModuleLightWidget::create>(Vec(98+6, 61+5), module, TriSEQ3::RESET_LIGHT)); + addParam(ParamWidget::create(Vec(132, 56), module, TriSEQ3::STEPS_PARAM, 1.0, 8.0, 8.0)); + addChild(ModuleLightWidget::create>(Vec(181.5, 66), module, TriSEQ3::GATES_LIGHT)); + addChild(ModuleLightWidget::create>(Vec(219.5, 66), module, TriSEQ3::ROW_LIGHTS + 0)); + addChild(ModuleLightWidget::create>(Vec(258, 66), module, TriSEQ3::ROW_LIGHTS + 1)); + addChild(ModuleLightWidget::create>(Vec(296.5, 66), module, TriSEQ3::ROW_LIGHTS + 2)); static const float portX[8] = {19, 57, 96, 134, 173, 211, 250, 288}; - addInput(createInput(Vec(portX[0]-1, 99-1), module, TriSEQ3::CLOCK_INPUT)); - addInput(createInput(Vec(portX[1]-1, 99-1), module, TriSEQ3::EXT_CLOCK_INPUT)); - addInput(createInput(Vec(portX[2]-1, 99-1), module, TriSEQ3::RESET_INPUT)); - addInput(createInput(Vec(portX[3]-1, 99-1), module, TriSEQ3::STEPS_INPUT)); - addOutput(createOutput(Vec(portX[4]-1, 99-1), module, TriSEQ3::GATES_OUTPUT)); - addOutput(createOutput(Vec(portX[5]-1, 99-1), module, TriSEQ3::ROW1_OUTPUT)); - addOutput(createOutput(Vec(portX[6]-1, 99-1), module, TriSEQ3::ROW2_OUTPUT)); - addOutput(createOutput(Vec(portX[7]-1, 99-1), module, TriSEQ3::ROW3_OUTPUT)); + addInput(Port::create(Vec(portX[0]-1, 99-1), Port::INPUT, module, TriSEQ3::CLOCK_INPUT)); + addInput(Port::create(Vec(portX[1]-1, 99-1), Port::INPUT, module, TriSEQ3::EXT_CLOCK_INPUT)); + addInput(Port::create(Vec(portX[2]-1, 99-1), Port::INPUT, module, TriSEQ3::RESET_INPUT)); + addInput(Port::create(Vec(portX[3]-1, 99-1), Port::INPUT, module, TriSEQ3::STEPS_INPUT)); + + addOutput(Port::create(Vec(portX[4]-1, 99-1), Port::OUTPUT, module, TriSEQ3::GATES_OUTPUT)); + addOutput(Port::create(Vec(portX[5]-1, 99-1), Port::OUTPUT, module, TriSEQ3::ROW1_OUTPUT)); + addOutput(Port::create(Vec(portX[6]-1, 99-1), Port::OUTPUT, module, TriSEQ3::ROW2_OUTPUT)); + addOutput(Port::create(Vec(portX[7]-1, 99-1), Port::OUTPUT, module, TriSEQ3::ROW3_OUTPUT)); for (int i = 0; i < 8; i++) { - addParam(createParam(Vec(portX[i]-3, 152), module, TriSEQ3::ROW1_PARAM + i, 0.0, 2.0, 0.0)); - addParam(createParam(Vec(portX[i]-3, 190), module, TriSEQ3::ROW2_PARAM + i, 0.0, 2.0, 0.0)); - addParam(createParam(Vec(portX[i]-3, 229), module, TriSEQ3::ROW3_PARAM + i, 0.0, 2.0, 0.0)); - addParam(createParam(Vec(portX[i]+2, 278-1), module, TriSEQ3::GATE_PARAM + i, 0.0, 1.0, 0.0)); - addChild(createLight>(Vec(portX[i]+8, 278+5), module, TriSEQ3::GATE_LIGHTS + i)); - addOutput(createOutput(Vec(portX[i]-1, 308-1), module, TriSEQ3::GATE_OUTPUT + i)); + addParam(ParamWidget::create(Vec(portX[i]-3, 152), module, TriSEQ3::ROW1_PARAM + i, 0.0, 2.0, 0.0)); + addParam(ParamWidget::create(Vec(portX[i]-3, 190), module, TriSEQ3::ROW2_PARAM + i, 0.0, 2.0, 0.0)); + addParam(ParamWidget::create(Vec(portX[i]-3, 229), module, TriSEQ3::ROW3_PARAM + i, 0.0, 2.0, 0.0)); + addParam(ParamWidget::create(Vec(portX[i]+2, 278-1), module, TriSEQ3::GATE_PARAM + i, 0.0, 1.0, 0.0)); + addChild(ModuleLightWidget::create>(Vec(portX[i]+8, 278+5), module, TriSEQ3::GATE_LIGHTS + i)); + addOutput(Port::create(Vec(portX[i]-1, 308-1), Port::OUTPUT, module, TriSEQ3::GATE_OUTPUT + i)); } } + +Model *modelTriSEQ3 = Model::create("dekstop", "TriSEQ3", "Tri SEQ-3", SEQUENCER_TAG); diff --git a/src/dekstop.cpp b/src/dekstop.cpp index 4750f91..be878b5 100644 --- a/src/dekstop.cpp +++ b/src/dekstop.cpp @@ -5,14 +5,12 @@ Plugin *plugin; void init(rack::Plugin *p) { plugin = p; - plugin->slug = "dekstop"; -#ifdef VERSION + plugin->slug = TOSTRING(SLUG);; p->version = TOSTRING(VERSION); -#endif p->website = "https://github.com/dekstop/vcvrackplugins_dekstop"; - p->addModel(createModel("dekstop", "TriSEQ3", "Tri-state SEQ-3", SEQUENCER_TAG)); - p->addModel(createModel("dekstop", "GateSEQ8", "Gate SEQ-8", SEQUENCER_TAG)); - p->addModel(createModel("dekstop", "Recorder2", "Recorder 2", UTILITY_TAG)); - p->addModel(createModel("dekstop", "Recorder8", "Recorder 8", UTILITY_TAG)); + p->addModel(modelGateSEQ8); + p->addModel(modelTriSEQ3); + p->addModel(modelRecorder2); + p->addModel(modelRecorder8); } diff --git a/src/dekstop.hpp b/src/dekstop.hpp index 128ed8a..5172c1d 100644 --- a/src/dekstop.hpp +++ b/src/dekstop.hpp @@ -5,35 +5,10 @@ using namespace rack; extern Plugin *plugin; -//////////////////// -// module widgets -//////////////////// +extern Model *modelGateSEQ8; +extern Model *modelTriSEQ3; -struct TriSEQ3Widget : ModuleWidget { - TriSEQ3Widget(); - json_t *toJsonData(); - void fromJsonData(json_t *root); -}; +extern Model *modelRecorder; +extern Model *modelRecorder2; +extern Model *modelRecorder8; -struct GateSEQ8Widget : ModuleWidget { - GateSEQ8Widget(); - json_t *toJsonData(); - void fromJsonData(json_t *root); -}; - -template -struct RecorderWidget : ModuleWidget { - RecorderWidget(); - json_t *toJsonData(); - void fromJsonData(json_t *root); -}; - -struct Recorder2Widget : RecorderWidget<2u> -{ - Recorder2Widget(); -}; - -struct Recorder8Widget : RecorderWidget<8u> -{ - Recorder8Widget(); -};