|
|
@@ -474,6 +474,7 @@ struct MIDICCToCVInterface : MidiIO, Module { |
|
|
|
|
|
|
|
int cc[NUM_OUTPUTS]; |
|
|
|
int ccNum[NUM_OUTPUTS]; |
|
|
|
bool ccNumInited[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()); |
|
|
|
if (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() { |
|
|
|
MIDICCToCVInterface *module = new MIDICCToCVInterface(); |
|
|
|
setModule(module); |
|
|
|
box.size = Vec(15 * 18, 380); |
|
|
|
box.size = Vec(16 * 15, 380); |
|
|
|
|
|
|
|
{ |
|
|
|
Panel *panel = new LightPanel(); |
|
|
@@ -612,17 +613,29 @@ MIDICCToCVWidget::MIDICCToCVWidget() { |
|
|
|
float labelHeight = 15; |
|
|
|
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->box.pos = Vec(margin, yPos); |
|
|
|
label->box.pos = Vec(box.size.x - margin - 11 * 15, margin); |
|
|
|
label->text = "MIDI CC to CV"; |
|
|
|
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->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); |
|
|
|
yPos += midiChoice->box.size.y + margin; |
|
|
|
} |
|
|
@@ -632,31 +645,31 @@ MIDICCToCVWidget::MIDICCToCVWidget() { |
|
|
|
label->box.pos = Vec(margin, yPos); |
|
|
|
label->text = "Channel"; |
|
|
|
addChild(label); |
|
|
|
yPos += labelHeight + margin; |
|
|
|
|
|
|
|
ChannelChoice *channelChoice = new ChannelChoice(); |
|
|
|
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); |
|
|
|
yPos += channelChoice->box.size.y + margin + 15; |
|
|
|
yPos += channelChoice->box.size.y + margin * 2; |
|
|
|
} |
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
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) { |
|
|
|
yPos += 40 + margin; |
|
|
|
yPos += 50 + margin; |
|
|
|
} else { |
|
|
|
yPos -= labelHeight + margin; |
|
|
|
} |
|
|
|