| @@ -474,6 +474,7 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||||
| int cc[NUM_OUTPUTS]; | int cc[NUM_OUTPUTS]; | ||||
| int ccNum[NUM_OUTPUTS]; | int ccNum[NUM_OUTPUTS]; | ||||
| bool ccNumInited[NUM_OUTPUTS]; | |||||
| float lights[NUM_OUTPUTS]; | float lights[NUM_OUTPUTS]; | ||||
| @@ -507,6 +508,7 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||||
| json_t *ccNumJ = json_object_get(rootJ, std::to_string(i).c_str()); | json_t *ccNumJ = json_object_get(rootJ, std::to_string(i).c_str()); | ||||
| if (ccNumJ) { | if (ccNumJ) { | ||||
| ccNum[i] = json_integer_value(ccNumJ); | ccNum[i] = json_integer_value(ccNumJ); | ||||
| ccNumInited[i] = true; | |||||
| } | } | ||||
| } | } | ||||
| @@ -562,45 +564,44 @@ void MIDICCToCVInterface::processMidi(std::vector<unsigned char> msg) { | |||||
| } | } | ||||
| struct CCNumItem : MenuItem { | |||||
| MIDICCToCVInterface *midiModule; | |||||
| int cc; | |||||
| int num; | |||||
| struct CCTextField : TextField { | |||||
| void draw(NVGcontext *vg); | |||||
| void onAction() { | |||||
| midiModule->ccNum[num] = cc; | |||||
| } | |||||
| int *ccNum; | |||||
| bool *inited; | |||||
| }; | }; | ||||
| struct CCNumChoice : ChoiceButton { | |||||
| MIDICCToCVInterface *midiModule; | |||||
| int num; | |||||
| void onAction() { | |||||
| Menu *menu = gScene->createMenu(); | |||||
| menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | |||||
| menu->box.size.x = box.size.x; | |||||
| for (int cc = 0; cc < 128; cc++) { | |||||
| CCNumItem *ccNumItem = new CCNumItem(); | |||||
| ccNumItem->midiModule = midiModule; | |||||
| ccNumItem->cc = cc; | |||||
| ccNumItem->num = num; | |||||
| ccNumItem->text = std::to_string(cc); | |||||
| menu->pushChild(ccNumItem); | |||||
| void CCTextField::draw(NVGcontext *vg) { | |||||
| // Note: this might not be the best way to do this. | |||||
| // Text field should have a virtual "onTextChange" function or something. | |||||
| // draw() is triggered way more frequently | |||||
| if (text.size() > 0) { | |||||
| if (*inited) { | |||||
| *inited = false; | |||||
| text = std::to_string(*ccNum); | |||||
| } | } | ||||
| } | |||||
| void step() { | |||||
| text = std::to_string(midiModule->ccNum[num]); | |||||
| } | |||||
| }; | |||||
| try { | |||||
| *ccNum = std::stoi(text, NULL, 10); | |||||
| // Only allow valid cc numbers | |||||
| if (*ccNum < 0 || *ccNum > 127) { | |||||
| text = ""; | |||||
| begin = 0; | |||||
| end = text.size(); | |||||
| } | |||||
| } catch (...) { | |||||
| text = ""; | |||||
| begin = 0; | |||||
| end = text.size(); | |||||
| } | |||||
| }; | |||||
| TextField::draw(vg); | |||||
| } | |||||
| MIDICCToCVWidget::MIDICCToCVWidget() { | MIDICCToCVWidget::MIDICCToCVWidget() { | ||||
| MIDICCToCVInterface *module = new MIDICCToCVInterface(); | MIDICCToCVInterface *module = new MIDICCToCVInterface(); | ||||
| setModule(module); | setModule(module); | ||||
| box.size = Vec(15 * 18, 380); | |||||
| box.size = Vec(16 * 15, 380); | |||||
| { | { | ||||
| Panel *panel = new LightPanel(); | Panel *panel = new LightPanel(); | ||||
| @@ -612,17 +613,29 @@ MIDICCToCVWidget::MIDICCToCVWidget() { | |||||
| float labelHeight = 15; | float labelHeight = 15; | ||||
| float yPos = margin; | float yPos = margin; | ||||
| addChild(createScrew<ScrewSilver>(Vec(margin, 0))); | |||||
| addChild(createScrew<ScrewSilver>(Vec(box.size.x - 15 - margin, 0))); | |||||
| addChild(createScrew<ScrewSilver>(Vec(margin, 365))); | |||||
| addChild(createScrew<ScrewSilver>(Vec(box.size.x - 15 - margin, 365))); | |||||
| { | { | ||||
| Label *label = new Label(); | Label *label = new Label(); | ||||
| label->box.pos = Vec(margin, yPos); | |||||
| label->box.pos = Vec(box.size.x - margin - 11 * 15, margin); | |||||
| label->text = "MIDI CC to CV"; | label->text = "MIDI CC to CV"; | ||||
| addChild(label); | addChild(label); | ||||
| yPos += labelHeight + margin; | |||||
| yPos = labelHeight * 2; | |||||
| } | |||||
| { | |||||
| Label *label = new Label(); | |||||
| label->box.pos = Vec(margin, yPos); | |||||
| label->text = "MIDI Interface"; | |||||
| addChild(label); | |||||
| MidiChoice *midiChoice = new MidiChoice(); | MidiChoice *midiChoice = new MidiChoice(); | ||||
| midiChoice->midiModule = dynamic_cast<MidiIO *>(module); | midiChoice->midiModule = dynamic_cast<MidiIO *>(module); | ||||
| midiChoice->box.pos = Vec(margin, yPos); | |||||
| midiChoice->box.size.x = box.size.x - 10; | |||||
| midiChoice->box.pos = Vec((box.size.x - 10) / 2 + margin, yPos); | |||||
| midiChoice->box.size.x = (box.size.x / 2.0) - margin; | |||||
| addChild(midiChoice); | addChild(midiChoice); | ||||
| yPos += midiChoice->box.size.y + margin; | yPos += midiChoice->box.size.y + margin; | ||||
| } | } | ||||
| @@ -632,31 +645,31 @@ MIDICCToCVWidget::MIDICCToCVWidget() { | |||||
| label->box.pos = Vec(margin, yPos); | label->box.pos = Vec(margin, yPos); | ||||
| label->text = "Channel"; | label->text = "Channel"; | ||||
| addChild(label); | addChild(label); | ||||
| yPos += labelHeight + margin; | |||||
| ChannelChoice *channelChoice = new ChannelChoice(); | ChannelChoice *channelChoice = new ChannelChoice(); | ||||
| channelChoice->midiModule = dynamic_cast<MidiIO *>(module); | channelChoice->midiModule = dynamic_cast<MidiIO *>(module); | ||||
| channelChoice->box.pos = Vec(margin, yPos); | |||||
| channelChoice->box.size.x = box.size.x - 10; | |||||
| channelChoice->box.pos = Vec((box.size.x - 10) / 2 + margin, yPos); | |||||
| channelChoice->box.size.x = (box.size.x / 2.0) - margin; | |||||
| addChild(channelChoice); | addChild(channelChoice); | ||||
| yPos += channelChoice->box.size.y + margin + 15; | |||||
| yPos += channelChoice->box.size.y + margin * 2; | |||||
| } | } | ||||
| for (int i = 0; i < MIDICCToCVInterface::NUM_OUTPUTS; i++) { | for (int i = 0; i < MIDICCToCVInterface::NUM_OUTPUTS; i++) { | ||||
| CCNumChoice *ccNumChoice = new CCNumChoice(); | |||||
| ccNumChoice->midiModule = module; | |||||
| ccNumChoice->num = module->ccNum[i]; | |||||
| ccNumChoice->box.pos = Vec(10 + (i % 4) * (67), yPos); | |||||
| ccNumChoice->box.size.x = 15 * 3; | |||||
| CCTextField *ccNumChoice = new CCTextField(); | |||||
| ccNumChoice->ccNum = &module->ccNum[i]; | |||||
| ccNumChoice->inited = &module->ccNumInited[i]; | |||||
| ccNumChoice->text = std::to_string(module->ccNum[i]); | |||||
| ccNumChoice->box.pos = Vec(10 + (i % 4) * (63), yPos); | |||||
| ccNumChoice->box.size.x = 15 * 2; | |||||
| addChild(ccNumChoice); | addChild(ccNumChoice); | ||||
| yPos += labelHeight + margin; | yPos += labelHeight + margin; | ||||
| addOutput(createOutput<PJ3410Port>(Vec(10 + (i % 4) * (67), yPos + 5), module, i)); | |||||
| addChild(createValueLight<SmallLight<GreenValueLight>>(Vec((i % 4) * (67) + 32, yPos + 5), &module->lights[i])); | |||||
| addOutput(createOutput<PJ3410Port>(Vec((i % 4) * (63) + 10, yPos + 5), module, i)); | |||||
| addChild(createValueLight<SmallLight<GreenValueLight>>(Vec((i % 4) * (63) + 32, yPos + 5), &module->lights[i])); | |||||
| if ((i + 1) % 4 == 0) { | if ((i + 1) % 4 == 0) { | ||||
| yPos += 40 + margin; | |||||
| yPos += 50 + margin; | |||||
| } else { | } else { | ||||
| yPos -= labelHeight + margin; | yPos -= labelHeight + margin; | ||||
| } | } | ||||