| @@ -22,6 +22,7 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||
| int cc[NUM_OUTPUTS]; | |||
| int ccNum[NUM_OUTPUTS]; | |||
| bool ccSync[NUM_OUTPUTS]; | |||
| bool ccSyncFirst[NUM_OUTPUTS]; | |||
| bool ccNumInited[NUM_OUTPUTS]; | |||
| bool onFocus[NUM_OUTPUTS]; | |||
| float lights[NUM_OUTPUTS]; | |||
| @@ -31,8 +32,9 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||
| for (int i = 0; i < NUM_OUTPUTS; i++) { | |||
| cc[i] = 0; | |||
| ccNum[i] = i; | |||
| ccSync[i] = true; | |||
| ccSyncFirst[i] = true; | |||
| onFocus[i] = false; | |||
| ccSync[i] = true; | |||
| } | |||
| } | |||
| @@ -51,7 +53,7 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||
| addBaseJson(rootJ); | |||
| for (int i = 0; i < NUM_OUTPUTS; i++) { | |||
| json_object_set_new(rootJ, ("ccNum" + std::to_string(i)).c_str(), json_integer(ccNum[i])); | |||
| if(outputs[i].active){ | |||
| if (outputs[i].active) { | |||
| json_object_set_new(rootJ, ("ccVal" + std::to_string(i)).c_str(), json_integer(cc[i])); | |||
| } | |||
| } | |||
| @@ -70,7 +72,6 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||
| json_t *ccValJ = json_object_get(rootJ, ("ccVal" + std::to_string(i)).c_str()); | |||
| if (ccValJ) { | |||
| cc[i] = json_integer_value(ccValJ); | |||
| ccSync[i] = false; | |||
| } | |||
| } | |||
| @@ -82,7 +83,6 @@ struct MIDICCToCVInterface : MidiIO, Module { | |||
| }; | |||
| void MIDICCToCVInterface::step() { | |||
| if (isPortOpen()) { | |||
| std::vector<unsigned char> message; | |||
| @@ -124,21 +124,26 @@ void MIDICCToCVInterface::processMidi(std::vector<unsigned char> msg) { | |||
| if (status == 0xb) { | |||
| for (int i = 0; i < NUM_OUTPUTS; i++) { | |||
| if (onFocus[i]) { | |||
| if (ccNum[i] != data1) { | |||
| ccSync[i] = false; | |||
| } | |||
| this->ccNum[i] = data1; | |||
| ccSync[i] = true; | |||
| ccSyncFirst[i] = true; | |||
| ccNum[i] = data1; | |||
| } | |||
| } | |||
| for (int i = 0; i < NUM_OUTPUTS; i++) { | |||
| if (data1 == ccNum[i]) { | |||
| if (!ccSync[i]) { | |||
| ccSync[i] = (cc[i] <= data2+1 && cc[i] >= data2-1) ; | |||
| break; | |||
| if (ccSyncFirst[i]) { | |||
| ccSyncFirst[i] = false; | |||
| ccSync[i] = data2 < cc[i]+2 && data2 > cc[i] - 2; | |||
| } | |||
| this->cc[i] = data2; | |||
| if (ccSync[i]) { | |||
| cc[i] = data2; | |||
| } else if (cc[i] == data2) { | |||
| ccSync[i] = true; | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -155,22 +160,21 @@ struct CCTextField : TextField { | |||
| void onMouseLeave(); | |||
| int *ccNum; | |||
| bool *inited; | |||
| bool *onFocus; | |||
| bool *ccSync; | |||
| int num; | |||
| MIDICCToCVInterface *module; | |||
| }; | |||
| void CCTextField::draw(NVGcontext *vg) { | |||
| /* This is necessary, since the save | |||
| * file is loaded after constructing the widget*/ | |||
| if (*inited) { | |||
| *inited = false; | |||
| text = std::to_string(*ccNum); | |||
| if (module->ccNumInited[num]) { | |||
| module->ccNumInited[num] = false; | |||
| text = std::to_string(module->ccNum[num]); | |||
| } | |||
| if (*onFocus) { | |||
| text = std::to_string(*ccNum); | |||
| if (module->onFocus[num]) { | |||
| text = std::to_string(module->ccNum[num]); | |||
| } | |||
| TextField::draw(vg); | |||
| @@ -178,23 +182,24 @@ void CCTextField::draw(NVGcontext *vg) { | |||
| void CCTextField::onMouseUpOpaque(int button) { | |||
| if (button == 1) { | |||
| *onFocus = false; | |||
| module->onFocus[num] = false; | |||
| } | |||
| } | |||
| void CCTextField::onMouseDownOpaque(int button) { | |||
| if (button == 1) { | |||
| *onFocus = true; | |||
| module->onFocus[num] = true; | |||
| } | |||
| } | |||
| void CCTextField::onMouseLeave() { | |||
| *onFocus = false; | |||
| module->onFocus[num] = false; | |||
| } | |||
| void CCTextField::onTextChange() { | |||
| int *ccNum = &module->ccNum[num]; | |||
| if (text.size() > 0) { | |||
| try { | |||
| *ccNum = std::stoi(text); | |||
| @@ -206,8 +211,8 @@ void CCTextField::onTextChange() { | |||
| return; | |||
| } | |||
| if (!*inited && *ccNum != std::stoi(text)) { | |||
| *ccSync = false; | |||
| if (!module->ccNumInited[num] && *ccNum != std::stoi(text)) { | |||
| module->ccSync[num] = true; | |||
| } | |||
| } catch (...) { | |||
| @@ -275,10 +280,8 @@ MIDICCToCVWidget::MIDICCToCVWidget() { | |||
| for (int i = 0; i < MIDICCToCVInterface::NUM_OUTPUTS; i++) { | |||
| CCTextField *ccNumChoice = new CCTextField(); | |||
| ccNumChoice->ccNum = &module->ccNum[i]; | |||
| ccNumChoice->inited = &module->ccNumInited[i]; | |||
| ccNumChoice->onFocus = &module->onFocus[i]; | |||
| ccNumChoice->ccSync = &module->ccSync[i]; | |||
| ccNumChoice->module = module; | |||
| ccNumChoice->num = i; | |||
| ccNumChoice->text = std::to_string(module->ccNum[i]); | |||
| ccNumChoice->box.pos = Vec(11 + (i % 4) * (63), yPos); | |||
| ccNumChoice->box.size.x = 29; | |||
| @@ -287,7 +290,8 @@ MIDICCToCVWidget::MIDICCToCVWidget() { | |||
| yPos += labelHeight + margin; | |||
| addOutput(createOutput<PJ3410Port>(Vec((i % 4) * (63) + 10, yPos + 5), module, i)); | |||
| addChild(createValueLight<SmallLight<RedValueLight>>(Vec((i % 4) * (63) + 32, yPos + 5), &module->lights[i])); | |||
| addChild(createValueLight<SmallLight<RedValueLight>>(Vec((i % 4) * (63) + 32, yPos + 5), | |||
| &module->lights[i])); | |||
| if ((i + 1) % 4 == 0) { | |||
| yPos += 47 + margin; | |||