| @@ -60,8 +60,8 @@ struct ModuleWidget : OpaqueWidget { | |||||
| std::vector<Port*> outputs; | std::vector<Port*> outputs; | ||||
| std::vector<ParamWidget*> params; | std::vector<ParamWidget*> params; | ||||
| ModuleWidget(Module *module); | |||||
| ~ModuleWidget(); | ~ModuleWidget(); | ||||
| void setModule(Module *module); | |||||
| /** Convenience functions for adding special widgets (calls addChild()) */ | /** Convenience functions for adding special widgets (calls addChild()) */ | ||||
| void addInput(Port *input); | void addInput(Port *input); | ||||
| void addOutput(Port *output); | void addOutput(Port *output); | ||||
| @@ -50,9 +50,9 @@ struct Module { | |||||
| /** For CPU usage meter */ | /** For CPU usage meter */ | ||||
| float cpuTime = 0.0; | 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) { | Module(int numParams, int numInputs, int numOutputs, int numLights = 0) { | ||||
| params.resize(numParams); | params.resize(numParams); | ||||
| inputs.resize(numInputs); | inputs.resize(numInputs); | ||||
| @@ -11,6 +11,7 @@ struct ModuleWidget; | |||||
| struct Module; | struct Module; | ||||
| struct Model; | struct Model; | ||||
| // Subclass this and return a pointer to a new one when init() is called | // Subclass this and return a pointer to a new one when init() is called | ||||
| struct Plugin { | struct Plugin { | ||||
| /** A list of the models available by this plugin, add with addModel() */ | /** A list of the models available by this plugin, add with addModel() */ | ||||
| @@ -39,6 +40,7 @@ struct Plugin { | |||||
| void addModel(Model *model); | void addModel(Model *model); | ||||
| }; | }; | ||||
| struct Model { | struct Model { | ||||
| Plugin *plugin = NULL; | Plugin *plugin = NULL; | ||||
| /** An identifier for the model, e.g. "VCO". Used for saving patches. The slug, manufacturerSlug pair must be unique. */ | /** 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; | std::list<ModelTag> tags; | ||||
| virtual ~Model() {} | virtual ~Model() {} | ||||
| /** Creates a headless Module */ | |||||
| virtual Module *createModule() { return NULL; } | virtual Module *createModule() { return NULL; } | ||||
| /** Creates a ModuleWidget with a Module attached */ | |||||
| virtual ModuleWidget *createModuleWidget() { return NULL; } | 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 pluginInit(); | ||||
| void pluginDestroy(); | void pluginDestroy(); | ||||
| void pluginLogIn(std::string email, std::string password); | void pluginLogIn(std::string email, std::string password); | ||||
| @@ -18,8 +18,9 @@ namespace rack { | |||||
| // helpers | // helpers | ||||
| //////////////////// | //////////////////// | ||||
| /** Deprecated, use Model::create<TModule, TModuleWidget>(...) instead */ | |||||
| template <class TModuleWidget, typename... Tags> | 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 { | struct TModel : Model { | ||||
| ModuleWidget *createModuleWidget() override { | ModuleWidget *createModuleWidget() override { | ||||
| ModuleWidget *moduleWidget = new TModuleWidget(); | ModuleWidget *moduleWidget = new TModuleWidget(); | ||||
| @@ -7,22 +7,22 @@ | |||||
| namespace rack { | namespace rack { | ||||
| ModuleWidget::ModuleWidget(Module *module) { | |||||
| if (module) { | |||||
| engineAddModule(module); | |||||
| } | |||||
| this->module = module; | |||||
| } | |||||
| ModuleWidget::~ModuleWidget() { | ModuleWidget::~ModuleWidget() { | ||||
| // Make sure WireWidget destructors are called *before* removing `module` from the rack. | // Make sure WireWidget destructors are called *before* removing `module` from the rack. | ||||
| disconnect(); | disconnect(); | ||||
| // Remove and delete the Module instance | // Remove and delete the Module instance | ||||
| setModule(NULL); | |||||
| } | |||||
| void ModuleWidget::setModule(Module *module) { | |||||
| if (this->module) { | |||||
| engineRemoveModule(this->module); | |||||
| delete this->module; | |||||
| } | |||||
| if (module) { | if (module) { | ||||
| engineAddModule(module); | |||||
| engineRemoveModule(module); | |||||
| delete module; | |||||
| module = NULL; | |||||
| } | } | ||||
| this->module = module; | |||||
| } | } | ||||
| void ModuleWidget::addInput(Port *input) { | 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 | * CV | ||||
| */ | */ | ||||
| struct MidiValue { | struct MidiValue { | ||||
| @@ -16,7 +16,7 @@ struct MidiValue { | |||||
| }; | }; | ||||
| struct MIDIToCVInterface : Module { | |||||
| struct MidiToCvInterface : Module { | |||||
| enum ParamIds { | enum ParamIds { | ||||
| RESET_PARAM, | RESET_PARAM, | ||||
| NUM_PARAMS | NUM_PARAMS | ||||
| @@ -51,12 +51,12 @@ struct MIDIToCVInterface : Module { | |||||
| SchmittTrigger resetTrigger; | 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.val = 64; | ||||
| // pitchWheel.tSmooth.set(0, 0); | // pitchWheel.tSmooth.set(0, 0); | ||||
| } | } | ||||
| ~MIDIToCVInterface() { | |||||
| ~MidiToCvInterface() { | |||||
| }; | }; | ||||
| void step() override; | void step() override; | ||||
| @@ -85,7 +85,7 @@ struct MIDIToCVInterface : Module { | |||||
| }; | }; | ||||
| /* | /* | ||||
| void MIDIToCVInterface::resetMidi() { | |||||
| void MidiToCvInterface::resetMidi() { | |||||
| mod.val = 0; | mod.val = 0; | ||||
| mod.tSmooth.set(0, 0); | mod.tSmooth.set(0, 0); | ||||
| pitchWheel.val = 64; | pitchWheel.val = 64; | ||||
| @@ -98,7 +98,7 @@ void MIDIToCVInterface::resetMidi() { | |||||
| } | } | ||||
| */ | */ | ||||
| void MIDIToCVInterface::step() { | |||||
| void MidiToCvInterface::step() { | |||||
| /* | /* | ||||
| if (isPortOpen()) { | if (isPortOpen()) { | ||||
| std::vector<unsigned char> message; | std::vector<unsigned char> message; | ||||
| @@ -143,7 +143,7 @@ void MIDIToCVInterface::step() { | |||||
| lights[ACTIVE_LIGHT].value = midiInput.isActive() ? 1.0 : 0.0; | lights[ACTIVE_LIGHT].value = midiInput.isActive() ? 1.0 : 0.0; | ||||
| } | } | ||||
| void MIDIToCVInterface::pressNote(int note) { | |||||
| void MidiToCvInterface::pressNote(int note) { | |||||
| // Remove existing similar note | // Remove existing similar note | ||||
| auto it = std::find(notes.begin(), notes.end(), note); | auto it = std::find(notes.begin(), notes.end(), note); | ||||
| if (it != notes.end()) | if (it != notes.end()) | ||||
| @@ -154,7 +154,7 @@ void MIDIToCVInterface::pressNote(int note) { | |||||
| gate = true; | gate = true; | ||||
| } | } | ||||
| void MIDIToCVInterface::releaseNote(int note) { | |||||
| void MidiToCvInterface::releaseNote(int note) { | |||||
| // Remove the note | // Remove the note | ||||
| auto it = std::find(notes.begin(), notes.end(), note); | auto it = std::find(notes.begin(), notes.end(), note); | ||||
| if (it != notes.end()) | 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 channel = msg[0] & 0xf; | ||||
| int status = (msg[0] >> 4) & 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) { | void init(rack::Plugin *p) { | ||||
| p->slug = "Core"; | p->slug = "Core"; | ||||
| #ifdef VERSION | |||||
| p->version = TOSTRING(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<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<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<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<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; | using namespace rack; | ||||
| extern Model *modelAudioInterface; | |||||
| extern Model *modelMidiToCvInterface; | |||||
| extern Model *modelBlank; | |||||
| extern Model *modelNotes; | |||||
| //////////////////// | //////////////////// | ||||
| // module widgets | // module widgets | ||||
| //////////////////// | //////////////////// | ||||
| struct AudioInterfaceWidget : ModuleWidget { | |||||
| AudioInterfaceWidget(); | |||||
| }; | |||||
| struct MidiToCVWidget : ModuleWidget { | |||||
| MidiToCVWidget(); | |||||
| }; | |||||
| // struct MIDICCToCVWidget : ModuleWidget { | // struct MIDICCToCVWidget : ModuleWidget { | ||||
| // MIDICCToCVWidget(); | // MIDICCToCVWidget(); | ||||
| @@ -35,25 +34,3 @@ struct MidiToCVWidget : ModuleWidget { | |||||
| // QuadMidiToCVWidget(); | // QuadMidiToCVWidget(); | ||||
| // void step() override; | // 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; | |||||
| }; | |||||