| @@ -60,8 +60,8 @@ struct ModuleWidget : OpaqueWidget { | |||
| std::vector<Port*> outputs; | |||
| std::vector<ParamWidget*> params; | |||
| ModuleWidget(Module *module); | |||
| ~ModuleWidget(); | |||
| void setModule(Module *module); | |||
| /** Convenience functions for adding special widgets (calls addChild()) */ | |||
| void addInput(Port *input); | |||
| void addOutput(Port *output); | |||
| @@ -50,9 +50,9 @@ struct Module { | |||
| /** For CPU usage meter */ | |||
| float cpuTime = 0.0; | |||
| /** Deprecated, use constructor below this one */ | |||
| Module() DEPRECATED {} | |||
| /** Constructs Module with a fixed number of params, inputs, and outputs */ | |||
| /** Constructs a Module with no params, inputs, outputs, and lights */ | |||
| Module() {} | |||
| /** Constructs a Module with a fixed number of params, inputs, outputs, and lights */ | |||
| Module(int numParams, int numInputs, int numOutputs, int numLights = 0) { | |||
| params.resize(numParams); | |||
| inputs.resize(numInputs); | |||
| @@ -11,6 +11,7 @@ struct ModuleWidget; | |||
| struct Module; | |||
| struct Model; | |||
| // Subclass this and return a pointer to a new one when init() is called | |||
| struct Plugin { | |||
| /** A list of the models available by this plugin, add with addModel() */ | |||
| @@ -39,6 +40,7 @@ struct Plugin { | |||
| void addModel(Model *model); | |||
| }; | |||
| struct Model { | |||
| Plugin *plugin = NULL; | |||
| /** An identifier for the model, e.g. "VCO". Used for saving patches. The slug, manufacturerSlug pair must be unique. */ | |||
| @@ -54,10 +56,43 @@ struct Model { | |||
| std::list<ModelTag> tags; | |||
| virtual ~Model() {} | |||
| /** Creates a headless Module */ | |||
| virtual Module *createModule() { return NULL; } | |||
| /** Creates a ModuleWidget with a Module attached */ | |||
| virtual ModuleWidget *createModuleWidget() { return NULL; } | |||
| /** Creates a ModuleWidget with no Module, useful for previews */ | |||
| virtual ModuleWidget *createModuleWidgetNull() { return NULL; } | |||
| /** Create Model subclass which constructs a specific Module and ModuleWidget subclass */ | |||
| template <typename TModule, typename TModuleWidget, typename... Tags> | |||
| static Model *create(std::string manufacturer, std::string slug, std::string name, Tags... tags) { | |||
| struct TModel : Model { | |||
| Module *createModule() override { | |||
| TModule *module = new TModule(); | |||
| return module; | |||
| } | |||
| ModuleWidget *createModuleWidget() override { | |||
| TModule *module = new TModule(); | |||
| TModuleWidget *moduleWidget = new TModuleWidget(module); | |||
| moduleWidget->model = this; | |||
| return moduleWidget; | |||
| } | |||
| ModuleWidget *createModuleWidgetNull() override { | |||
| TModuleWidget *moduleWidget = new TModuleWidget(NULL); | |||
| moduleWidget->model = this; | |||
| return moduleWidget; | |||
| } | |||
| }; | |||
| TModel *o = new TModel(); | |||
| o->manufacturer = manufacturer; | |||
| o->slug = slug; | |||
| o->name = name; | |||
| o->tags = {tags...}; | |||
| return o; | |||
| } | |||
| }; | |||
| void pluginInit(); | |||
| void pluginDestroy(); | |||
| void pluginLogIn(std::string email, std::string password); | |||
| @@ -18,8 +18,9 @@ namespace rack { | |||
| // helpers | |||
| //////////////////// | |||
| /** Deprecated, use Model::create<TModule, TModuleWidget>(...) instead */ | |||
| template <class TModuleWidget, typename... Tags> | |||
| Model *createModel(std::string manufacturer, std::string slug, std::string name, Tags... tags) { | |||
| DEPRECATED Model *createModel(std::string manufacturer, std::string slug, std::string name, Tags... tags) { | |||
| struct TModel : Model { | |||
| ModuleWidget *createModuleWidget() override { | |||
| ModuleWidget *moduleWidget = new TModuleWidget(); | |||
| @@ -7,22 +7,22 @@ | |||
| namespace rack { | |||
| ModuleWidget::ModuleWidget(Module *module) { | |||
| if (module) { | |||
| engineAddModule(module); | |||
| } | |||
| this->module = module; | |||
| } | |||
| ModuleWidget::~ModuleWidget() { | |||
| // Make sure WireWidget destructors are called *before* removing `module` from the rack. | |||
| disconnect(); | |||
| // Remove and delete the Module instance | |||
| setModule(NULL); | |||
| } | |||
| void ModuleWidget::setModule(Module *module) { | |||
| if (this->module) { | |||
| engineRemoveModule(this->module); | |||
| delete this->module; | |||
| } | |||
| if (module) { | |||
| engineAddModule(module); | |||
| engineRemoveModule(module); | |||
| delete module; | |||
| module = NULL; | |||
| } | |||
| this->module = module; | |||
| } | |||
| void ModuleWidget::addInput(Port *input) { | |||
| @@ -210,99 +210,102 @@ void AudioInterface::step() { | |||
| } | |||
| AudioInterfaceWidget::AudioInterfaceWidget() { | |||
| AudioInterface *module = new AudioInterface(); | |||
| setModule(module); | |||
| box.size = Vec(15*12, 380); | |||
| { | |||
| Panel *panel = new LightPanel(); | |||
| panel->box.size = box.size; | |||
| addChild(panel); | |||
| } | |||
| struct AudioInterfaceWidget : ModuleWidget { | |||
| AudioInterfaceWidget(AudioInterface *module) : ModuleWidget(module) { | |||
| box.size = Vec(15*12, 380); | |||
| { | |||
| Panel *panel = new LightPanel(); | |||
| panel->box.size = box.size; | |||
| addChild(panel); | |||
| } | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365))); | |||
| Vec margin = Vec(5, 2); | |||
| float labelHeight = 15; | |||
| float yPos = margin.y + 100; | |||
| float xPos; | |||
| { | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(margin.x, yPos); | |||
| label->text = "Outputs (DACs)"; | |||
| addChild(label); | |||
| yPos += labelHeight + margin.y; | |||
| } | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365))); | |||
| Vec margin = Vec(5, 2); | |||
| float labelHeight = 15; | |||
| float yPos = margin.y + 100; | |||
| float xPos; | |||
| { | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(margin.x, yPos); | |||
| label->text = "Outputs (DACs)"; | |||
| addChild(label); | |||
| yPos += labelHeight + margin.y; | |||
| } | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 0; i < 4; i++) { | |||
| addInput(Port::create<PJ3410Port>(Vec(xPos, yPos), Port::INPUT, module, AudioInterface::AUDIO_INPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| addChild(label); | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 0; i < 4; i++) { | |||
| addInput(Port::create<PJ3410Port>(Vec(xPos, yPos), Port::INPUT, module, AudioInterface::AUDIO_INPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| addChild(label); | |||
| xPos += 37 + margin.x; | |||
| } | |||
| yPos += 35 + margin.y; | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 4; i < 8; i++) { | |||
| addInput(Port::create<PJ3410Port>(Vec(xPos, yPos), Port::INPUT, module, AudioInterface::AUDIO_INPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| addChild(label); | |||
| xPos += 37 + margin.x; | |||
| } | |||
| yPos += 35 + margin.y; | |||
| { | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(margin.x, yPos); | |||
| label->text = "Inputs (ADCs)"; | |||
| addChild(label); | |||
| yPos += labelHeight + margin.y; | |||
| } | |||
| xPos += 37 + margin.x; | |||
| } | |||
| yPos += 35 + margin.y; | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 4; i < 8; i++) { | |||
| addInput(Port::create<PJ3410Port>(Vec(xPos, yPos), Port::INPUT, module, AudioInterface::AUDIO_INPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| addChild(label); | |||
| xPos += 37 + margin.x; | |||
| } | |||
| yPos += 35 + margin.y; | |||
| { | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(margin.x, yPos); | |||
| label->text = "Inputs (ADCs)"; | |||
| addChild(label); | |||
| yPos += labelHeight + margin.y; | |||
| } | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 0; i < 4; i++) { | |||
| Port *port = Port::create<PJ3410Port>(Vec(xPos, yPos), Port::OUTPUT, module, AudioInterface::AUDIO_OUTPUT + i); | |||
| addOutput(port); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| addChild(label); | |||
| xPos += 37 + margin.x; | |||
| } | |||
| yPos += 35 + margin.y; | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 4; i < 8; i++) { | |||
| addOutput(Port::create<PJ3410Port>(Vec(xPos, yPos), Port::OUTPUT, module, AudioInterface::AUDIO_OUTPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| addChild(label); | |||
| xPos += 37 + margin.x; | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 0; i < 4; i++) { | |||
| Port *port = Port::create<PJ3410Port>(Vec(xPos, yPos), Port::OUTPUT, module, AudioInterface::AUDIO_OUTPUT + i); | |||
| addOutput(port); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| addChild(label); | |||
| xPos += 37 + margin.x; | |||
| } | |||
| yPos += 35 + margin.y; | |||
| yPos += 5; | |||
| xPos = 10; | |||
| for (int i = 4; i < 8; i++) { | |||
| addOutput(Port::create<PJ3410Port>(Vec(xPos, yPos), Port::OUTPUT, module, AudioInterface::AUDIO_OUTPUT + i)); | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(xPos + 4, yPos + 28); | |||
| label->text = stringf("%d", i + 1); | |||
| addChild(label); | |||
| xPos += 37 + margin.x; | |||
| } | |||
| yPos += 35 + margin.y; | |||
| AudioWidget *audioWidget = construct<USB_B_AudioWidget>(); | |||
| audioWidget->audioIO = &module->audioIO; | |||
| addChild(audioWidget); | |||
| // Lights | |||
| addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(40, 20), module, AudioInterface::ACTIVE_LIGHT)); | |||
| } | |||
| yPos += 35 + margin.y; | |||
| }; | |||
| AudioWidget *audioWidget = construct<USB_B_AudioWidget>(); | |||
| audioWidget->audioIO = &module->audioIO; | |||
| addChild(audioWidget); | |||
| // Lights | |||
| addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(40, 20), module, AudioInterface::ACTIVE_LIGHT)); | |||
| } | |||
| Model *modelAudioInterface = Model::create<AudioInterface, AudioInterfaceWidget>("Core", "AudioInterface", "Audio Interface", EXTERNAL_TAG); | |||
| @@ -56,58 +56,68 @@ struct ModuleResizeHandle : Widget { | |||
| }; | |||
| BlankWidget::BlankWidget() { | |||
| box.size = Vec(RACK_GRID_WIDTH * 10, RACK_GRID_HEIGHT); | |||
| struct BlankWidget : ModuleWidget { | |||
| Panel *panel; | |||
| Widget *topRightScrew; | |||
| Widget *bottomRightScrew; | |||
| Widget *rightHandle; | |||
| BlankWidget(Module *module) : ModuleWidget(module) { | |||
| box.size = Vec(RACK_GRID_WIDTH * 10, RACK_GRID_HEIGHT); | |||
| { | |||
| panel = new LightPanel(); | |||
| panel->box.size = box.size; | |||
| addChild(panel); | |||
| } | |||
| { | |||
| panel = new LightPanel(); | |||
| panel->box.size = box.size; | |||
| addChild(panel); | |||
| ModuleResizeHandle *leftHandle = new ModuleResizeHandle(); | |||
| ModuleResizeHandle *rightHandle = new ModuleResizeHandle(); | |||
| rightHandle->right = true; | |||
| this->rightHandle = rightHandle; | |||
| addChild(leftHandle); | |||
| addChild(rightHandle); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| topRightScrew = Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)); | |||
| bottomRightScrew = Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)); | |||
| addChild(topRightScrew); | |||
| addChild(bottomRightScrew); | |||
| } | |||
| ModuleResizeHandle *leftHandle = new ModuleResizeHandle(); | |||
| ModuleResizeHandle *rightHandle = new ModuleResizeHandle(); | |||
| rightHandle->right = true; | |||
| this->rightHandle = rightHandle; | |||
| addChild(leftHandle); | |||
| addChild(rightHandle); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| topRightScrew = Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)); | |||
| bottomRightScrew = Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)); | |||
| addChild(topRightScrew); | |||
| addChild(bottomRightScrew); | |||
| } | |||
| void BlankWidget::step() { | |||
| panel->box.size = box.size; | |||
| topRightScrew->box.pos.x = box.size.x - 30; | |||
| bottomRightScrew->box.pos.x = box.size.x - 30; | |||
| if (box.size.x < RACK_GRID_WIDTH * 6) { | |||
| topRightScrew->visible = bottomRightScrew->visible = false; | |||
| } | |||
| else { | |||
| topRightScrew->visible = bottomRightScrew->visible = true; | |||
| void step() override { | |||
| panel->box.size = box.size; | |||
| topRightScrew->box.pos.x = box.size.x - 30; | |||
| bottomRightScrew->box.pos.x = box.size.x - 30; | |||
| if (box.size.x < RACK_GRID_WIDTH * 6) { | |||
| topRightScrew->visible = bottomRightScrew->visible = false; | |||
| } | |||
| else { | |||
| topRightScrew->visible = bottomRightScrew->visible = true; | |||
| } | |||
| rightHandle->box.pos.x = box.size.x - rightHandle->box.size.x; | |||
| ModuleWidget::step(); | |||
| } | |||
| rightHandle->box.pos.x = box.size.x - rightHandle->box.size.x; | |||
| ModuleWidget::step(); | |||
| } | |||
| json_t *BlankWidget::toJson() { | |||
| json_t *rootJ = ModuleWidget::toJson(); | |||
| json_t *toJson() override { | |||
| json_t *rootJ = ModuleWidget::toJson(); | |||
| // // width | |||
| json_object_set_new(rootJ, "width", json_real(box.size.x)); | |||
| return rootJ; | |||
| } | |||
| // // width | |||
| json_object_set_new(rootJ, "width", json_real(box.size.x)); | |||
| void fromJson(json_t *rootJ) override { | |||
| ModuleWidget::fromJson(rootJ); | |||
| return rootJ; | |||
| } | |||
| // width | |||
| json_t *widthJ = json_object_get(rootJ, "width"); | |||
| if (widthJ) | |||
| box.size.x = json_number_value(widthJ); | |||
| } | |||
| }; | |||
| void BlankWidget::fromJson(json_t *rootJ) { | |||
| ModuleWidget::fromJson(rootJ); | |||
| // width | |||
| json_t *widthJ = json_object_get(rootJ, "width"); | |||
| if (widthJ) | |||
| box.size.x = json_number_value(widthJ); | |||
| } | |||
| Model *modelBlank = Model::create<Module, BlankWidget>("Core", "Blank", "Blank", BLANK_TAG); | |||
| @@ -6,7 +6,7 @@ | |||
| /* | |||
| * MIDIToCVInterface converts midi note on/off events, velocity , channel aftertouch, pitch wheel and mod wheel to | |||
| * MidiToCvInterface converts midi note on/off events, velocity , channel aftertouch, pitch wheel and mod wheel to | |||
| * CV | |||
| */ | |||
| struct MidiValue { | |||
| @@ -16,7 +16,7 @@ struct MidiValue { | |||
| }; | |||
| struct MIDIToCVInterface : Module { | |||
| struct MidiToCvInterface : Module { | |||
| enum ParamIds { | |||
| RESET_PARAM, | |||
| NUM_PARAMS | |||
| @@ -51,12 +51,12 @@ struct MIDIToCVInterface : Module { | |||
| SchmittTrigger resetTrigger; | |||
| MIDIToCVInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| MidiToCvInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| pitchWheel.val = 64; | |||
| // pitchWheel.tSmooth.set(0, 0); | |||
| } | |||
| ~MIDIToCVInterface() { | |||
| ~MidiToCvInterface() { | |||
| }; | |||
| void step() override; | |||
| @@ -85,7 +85,7 @@ struct MIDIToCVInterface : Module { | |||
| }; | |||
| /* | |||
| void MIDIToCVInterface::resetMidi() { | |||
| void MidiToCvInterface::resetMidi() { | |||
| mod.val = 0; | |||
| mod.tSmooth.set(0, 0); | |||
| pitchWheel.val = 64; | |||
| @@ -98,7 +98,7 @@ void MIDIToCVInterface::resetMidi() { | |||
| } | |||
| */ | |||
| void MIDIToCVInterface::step() { | |||
| void MidiToCvInterface::step() { | |||
| /* | |||
| if (isPortOpen()) { | |||
| std::vector<unsigned char> message; | |||
| @@ -143,7 +143,7 @@ void MIDIToCVInterface::step() { | |||
| lights[ACTIVE_LIGHT].value = midiInput.isActive() ? 1.0 : 0.0; | |||
| } | |||
| void MIDIToCVInterface::pressNote(int note) { | |||
| void MidiToCvInterface::pressNote(int note) { | |||
| // Remove existing similar note | |||
| auto it = std::find(notes.begin(), notes.end(), note); | |||
| if (it != notes.end()) | |||
| @@ -154,7 +154,7 @@ void MIDIToCVInterface::pressNote(int note) { | |||
| gate = true; | |||
| } | |||
| void MIDIToCVInterface::releaseNote(int note) { | |||
| void MidiToCvInterface::releaseNote(int note) { | |||
| // Remove the note | |||
| auto it = std::find(notes.begin(), notes.end(), note); | |||
| if (it != notes.end()) | |||
| @@ -174,7 +174,7 @@ void MIDIToCVInterface::releaseNote(int note) { | |||
| } | |||
| } | |||
| void MIDIToCVInterface::processMidi(std::vector<unsigned char> msg) { | |||
| void MidiToCvInterface::processMidi(std::vector<unsigned char> msg) { | |||
| /* | |||
| int channel = msg[0] & 0xf; | |||
| int status = (msg[0] >> 4) & 0xf; | |||
| @@ -229,55 +229,58 @@ void MIDIToCVInterface::processMidi(std::vector<unsigned char> msg) { | |||
| } | |||
| MidiToCVWidget::MidiToCVWidget() { | |||
| MIDIToCVInterface *module = new MIDIToCVInterface(); | |||
| setModule(module); | |||
| box.size = Vec(15 * 9, 380); | |||
| struct MidiToCvInterfaceWidget : ModuleWidget { | |||
| MidiToCvInterfaceWidget(MidiToCvInterface *module) : ModuleWidget(module) { | |||
| box.size = Vec(15 * 9, 380); | |||
| { | |||
| Panel *panel = new LightPanel(); | |||
| panel->box.size = box.size; | |||
| addChild(panel); | |||
| } | |||
| { | |||
| Panel *panel = new LightPanel(); | |||
| panel->box.size = box.size; | |||
| addChild(panel); | |||
| } | |||
| float margin = 5; | |||
| float labelHeight = 15; | |||
| float yPos = margin; | |||
| float yGap = 35; | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365))); | |||
| { | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(box.size.x - margin - 7 * 15, margin); | |||
| label->text = "MIDI to CV"; | |||
| addChild(label); | |||
| yPos = labelHeight * 2; | |||
| } | |||
| float margin = 5; | |||
| float labelHeight = 15; | |||
| float yPos = margin; | |||
| float yGap = 35; | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365))); | |||
| { | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(box.size.x - margin - 7 * 15, margin); | |||
| label->text = "MIDI to CV"; | |||
| addChild(label); | |||
| yPos = labelHeight * 2; | |||
| } | |||
| addParam(ParamWidget::create<LEDButton>(Vec(7 * 15, labelHeight), module, MidiToCvInterface::RESET_PARAM, 0.0, 1.0, 0.0)); | |||
| addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(7 * 15 + 5, labelHeight + 5), module, MidiToCvInterface::RESET_LIGHT)); | |||
| addParam(ParamWidget::create<LEDButton>(Vec(7 * 15, labelHeight), module, MIDIToCVInterface::RESET_PARAM, 0.0, 1.0, 0.0)); | |||
| addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(7 * 15 + 5, labelHeight + 5), module, MIDIToCVInterface::RESET_LIGHT)); | |||
| std::string labels[MidiToCvInterface::NUM_OUTPUTS] = {"1V/oct", "Gate", "Velocity", "Mod Wheel", "Pitch Wheel", "Aftertouch"}; | |||
| std::string labels[MIDIToCVInterface::NUM_OUTPUTS] = {"1V/oct", "Gate", "Velocity", "Mod Wheel", "Pitch Wheel", "Aftertouch"}; | |||
| for (int i = 0; i < MidiToCvInterface::NUM_OUTPUTS; i++) { | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(margin, yPos); | |||
| label->text = labels[i]; | |||
| addChild(label); | |||
| for (int i = 0; i < MIDIToCVInterface::NUM_OUTPUTS; i++) { | |||
| Label *label = new Label(); | |||
| label->box.pos = Vec(margin, yPos); | |||
| label->text = labels[i]; | |||
| addChild(label); | |||
| addOutput(Port::create<PJ3410Port>(Vec(15 * 6, yPos - 5), Port::OUTPUT, module, i)); | |||
| addOutput(Port::create<PJ3410Port>(Vec(15 * 6, yPos - 5), Port::OUTPUT, module, i)); | |||
| yPos += yGap + margin; | |||
| } | |||
| MidiWidget *midiWidget = construct<MIDI_DIN_MidiWidget>(); | |||
| midiWidget->midiIO = &module->midiInput; | |||
| addChild(midiWidget); | |||
| yPos += yGap + margin; | |||
| // Lights | |||
| addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(40, 20), module, MidiToCvInterface::ACTIVE_LIGHT)); | |||
| } | |||
| }; | |||
| MidiWidget *midiWidget = construct<MIDI_DIN_MidiWidget>(); | |||
| midiWidget->midiIO = &module->midiInput; | |||
| addChild(midiWidget); | |||
| // Lights | |||
| addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(40, 20), module, MIDIToCVInterface::ACTIVE_LIGHT)); | |||
| } | |||
| Model *modelMidiToCvInterface = Model::create<MidiToCvInterface, MidiToCvInterfaceWidget>("Core", "MIDIToCVInterface", "MIDI-to-CV Interface", MIDI_TAG, EXTERNAL_TAG); | |||
| @@ -4,41 +4,48 @@ using namespace rack; | |||
| NotesWidget::NotesWidget() { | |||
| box.size = Vec(RACK_GRID_WIDTH * 18, RACK_GRID_HEIGHT); | |||
| { | |||
| Panel *panel = new LightPanel(); | |||
| panel->box.size = box.size; | |||
| addChild(panel); | |||
| struct NotesWidget : ModuleWidget { | |||
| TextField *textField; | |||
| NotesWidget(Module *module) : ModuleWidget(module) { | |||
| box.size = Vec(RACK_GRID_WIDTH * 18, RACK_GRID_HEIGHT); | |||
| { | |||
| Panel *panel = new LightPanel(); | |||
| panel->box.size = box.size; | |||
| addChild(panel); | |||
| } | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365))); | |||
| textField = new TextField(); | |||
| textField->box.pos = Vec(15, 15); | |||
| textField->box.size = box.size.minus(Vec(30, 30)); | |||
| textField->multiline = true; | |||
| addChild(textField); | |||
| } | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365))); | |||
| json_t *toJson() override { | |||
| json_t *rootJ = ModuleWidget::toJson(); | |||
| textField = new TextField(); | |||
| textField->box.pos = Vec(15, 15); | |||
| textField->box.size = box.size.minus(Vec(30, 30)); | |||
| textField->multiline = true; | |||
| addChild(textField); | |||
| } | |||
| // text | |||
| json_object_set_new(rootJ, "text", json_string(textField->text.c_str())); | |||
| json_t *NotesWidget::toJson() { | |||
| json_t *rootJ = ModuleWidget::toJson(); | |||
| return rootJ; | |||
| } | |||
| // text | |||
| json_object_set_new(rootJ, "text", json_string(textField->text.c_str())); | |||
| void fromJson(json_t *rootJ) override { | |||
| ModuleWidget::fromJson(rootJ); | |||
| return rootJ; | |||
| } | |||
| // text | |||
| json_t *textJ = json_object_get(rootJ, "text"); | |||
| if (textJ) | |||
| textField->text = json_string_value(textJ); | |||
| } | |||
| }; | |||
| void NotesWidget::fromJson(json_t *rootJ) { | |||
| ModuleWidget::fromJson(rootJ); | |||
| // text | |||
| json_t *textJ = json_object_get(rootJ, "text"); | |||
| if (textJ) | |||
| textField->text = json_string_value(textJ); | |||
| } | |||
| Model *modelNotes = Model::create<Module, NotesWidget>("Core", "Notes", "Notes", BLANK_TAG); | |||
| @@ -3,18 +3,16 @@ | |||
| void init(rack::Plugin *p) { | |||
| p->slug = "Core"; | |||
| #ifdef VERSION | |||
| p->version = TOSTRING(VERSION); | |||
| #endif | |||
| p->addModel(createModel<AudioInterfaceWidget>("Core", "AudioInterface", "Audio Interface", EXTERNAL_TAG)); | |||
| p->addModel(modelAudioInterface); | |||
| p->addModel(modelMidiToCvInterface); | |||
| p->addModel(modelBlank); | |||
| p->addModel(modelNotes); | |||
| p->addModel(createModel<MidiToCVWidget>("Core", "MIDIToCVInterface", "MIDI-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
| // TODO | |||
| // p->addModel(createModel<MIDICCToCVWidget>("Core", "MIDICCToCVInterface", "MIDI CC-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
| // p->addModel(createModel<MIDIClockToCVWidget>("Core", "MIDIClockToCVInterface", "MIDI Clock-to-CV Interface", MIDI_TAG, EXTERNAL_TAG, CLOCK_TAG)); | |||
| // p->addModel(createModel<MIDITriggerToCVWidget>("Core", "MIDITriggerToCVInterface", "MIDI Trigger-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
| // p->addModel(createModel<QuadMidiToCVWidget>("Core", "QuadMIDIToCVInterface", "Quad MIDI-to-CV Interface", MIDI_TAG, EXTERNAL_TAG, QUAD_TAG)); | |||
| p->addModel(createModel<BlankWidget>("Core", "Blank", "Blank", BLANK_TAG)); | |||
| p->addModel(createModel<NotesWidget>("Core", "Notes", "Notes", BLANK_TAG)); | |||
| } | |||
| @@ -4,17 +4,16 @@ | |||
| using namespace rack; | |||
| extern Model *modelAudioInterface; | |||
| extern Model *modelMidiToCvInterface; | |||
| extern Model *modelBlank; | |||
| extern Model *modelNotes; | |||
| //////////////////// | |||
| // module widgets | |||
| //////////////////// | |||
| struct AudioInterfaceWidget : ModuleWidget { | |||
| AudioInterfaceWidget(); | |||
| }; | |||
| struct MidiToCVWidget : ModuleWidget { | |||
| MidiToCVWidget(); | |||
| }; | |||
| // struct MIDICCToCVWidget : ModuleWidget { | |||
| // MIDICCToCVWidget(); | |||
| @@ -35,25 +34,3 @@ struct MidiToCVWidget : ModuleWidget { | |||
| // QuadMidiToCVWidget(); | |||
| // void step() override; | |||
| // }; | |||
| struct BridgeWidget : ModuleWidget { | |||
| BridgeWidget(); | |||
| }; | |||
| struct BlankWidget : ModuleWidget { | |||
| Panel *panel; | |||
| Widget *topRightScrew; | |||
| Widget *bottomRightScrew; | |||
| Widget *rightHandle; | |||
| BlankWidget(); | |||
| void step() override; | |||
| json_t *toJson() override; | |||
| void fromJson(json_t *rootJ) override; | |||
| }; | |||
| struct NotesWidget : ModuleWidget { | |||
| TextField *textField; | |||
| NotesWidget(); | |||
| json_t *toJson() override; | |||
| void fromJson(json_t *rootJ) override; | |||
| }; | |||