diff --git a/src/Core/MIDI_CC.cpp b/src/Core/MIDI_CC.cpp index 5dd11bd3..fc6f86cf 100644 --- a/src/Core/MIDI_CC.cpp +++ b/src/Core/MIDI_CC.cpp @@ -18,8 +18,8 @@ struct MIDI_CC : Module { midi::InputQueue midiInput; int8_t values[128]; - int learningId = -1; - int learnedCcs[16] = {}; + int learningId; + int learnedCcs[16]; dsp::ExponentialFilter valueFilters[16]; int8_t lastValues[16] = {}; @@ -76,20 +76,24 @@ struct MIDI_CC : Module { switch (msg.getStatus()) { // cc case 0xb: { - uint8_t cc = msg.getNote(); - // Learn - if (learningId >= 0 && values[cc] != msg.data2) { - learnedCcs[learningId] = cc; - learningId = -1; - } - // Allow CC to be negative if the 8th bit is set. - // The gamepad driver abuses this, for example. - values[cc] = msg.data2; + processCC(msg); } break; default: break; } } + void processCC(midi::Message msg) { + uint8_t cc = msg.getNote(); + // Learn + if (learningId >= 0 && values[cc] != msg.data2) { + learnedCcs[learningId] = cc; + learningId = -1; + } + // Allow CC to be negative if the 8th bit is set. + // The gamepad driver abuses this, for example. + values[cc] = msg.data2; + } + json_t *dataToJson() override { json_t *rootJ = json_object(); diff --git a/src/Core/MIDI_Gate.cpp b/src/Core/MIDI_Gate.cpp index 61d7c878..70bcaf8f 100644 --- a/src/Core/MIDI_Gate.cpp +++ b/src/Core/MIDI_Gate.cpp @@ -46,31 +46,6 @@ struct MIDI_Gate : Module { } } - void pressNote(uint8_t note, uint8_t vel) { - // Learn - if (learningId >= 0) { - learnedNotes[learningId] = note; - learningId = -1; - } - // Find id - for (int i = 0; i < 16; i++) { - if (learnedNotes[i] == note) { - gates[i] = true; - gateTimes[i] = 1e-3f; - velocities[i] = vel; - } - } - } - - void releaseNote(uint8_t note) { - // Find id - for (int i = 0; i < 16; i++) { - if (learnedNotes[i] == note) { - gates[i] = false; - } - } - } - void step() override { midi::Message msg; while (midiInput.shift(&msg)) { @@ -113,6 +88,31 @@ struct MIDI_Gate : Module { } } + void pressNote(uint8_t note, uint8_t vel) { + // Learn + if (learningId >= 0) { + learnedNotes[learningId] = note; + learningId = -1; + } + // Find id + for (int i = 0; i < 16; i++) { + if (learnedNotes[i] == note) { + gates[i] = true; + gateTimes[i] = 1e-3f; + velocities[i] = vel; + } + } + } + + void releaseNote(uint8_t note) { + // Find id + for (int i = 0; i < 16; i++) { + if (learnedNotes[i] == note) { + gates[i] = false; + } + } + } + json_t *dataToJson() override { json_t *rootJ = json_object(); diff --git a/src/Core/MIDI_Map.cpp b/src/Core/MIDI_Map.cpp index 7505d144..1dea6cba 100644 --- a/src/Core/MIDI_Map.cpp +++ b/src/Core/MIDI_Map.cpp @@ -17,8 +17,9 @@ struct MIDI_Map : Module { midi::InputQueue midiInput; int8_t values[128]; - int learningId = -1; - int learnedCcs[16] = {}; + int learningId; + int lastLearnedCc; + int learnedCcs[8]; dsp::ExponentialFilter valueFilters[8]; MIDI_Map() { @@ -27,10 +28,71 @@ struct MIDI_Map : Module { } void onReset() override { + learningId = -1; + lastLearnedCc = -1; + for (int i = 0; i < 8; i++) { + learnedCcs[i] = -1; + } midiInput.reset(); } void step() override { + midi::Message msg; + while (midiInput.shift(&msg)) { + processMessage(msg); + } + } + + void processMessage(midi::Message msg) { + switch (msg.getStatus()) { + // cc + case 0xb: { + processCC(msg); + } break; + default: break; + } + } + + void processCC(midi::Message msg) { + uint8_t cc = msg.getNote(); + // Learn + if (learningId >= 0 && values[cc] != msg.data2) { + if (lastLearnedCc != cc) { + learnedCcs[learningId] = cc; + lastLearnedCc = cc; + if (++learningId >= 8) + learningId = -1; + } + } + values[cc] = msg.getValue(); + } + + json_t *dataToJson() override { + json_t *rootJ = json_object(); + + json_t *ccsJ = json_array(); + for (int i = 0; i < 8; i++) { + json_array_append_new(ccsJ, json_integer(learnedCcs[i])); + } + json_object_set_new(rootJ, "ccs", ccsJ); + + json_object_set_new(rootJ, "midi", midiInput.toJson()); + return rootJ; + } + + void dataFromJson(json_t *rootJ) override { + json_t *ccsJ = json_object_get(rootJ, "ccs"); + if (ccsJ) { + for (int i = 0; i < 8; i++) { + json_t *ccJ = json_array_get(ccsJ, i); + if (ccJ) + learnedCcs[i] = json_integer_value(ccJ); + } + } + + json_t *midiJ = json_object_get(rootJ, "midi"); + if (midiJ) + midiInput.fromJson(midiJ); } }; @@ -66,11 +128,24 @@ struct MIDI_MapChoice : LedDisplayChoice { color.a = 1.0; bgColor = color; bgColor.a = 0.15; + + // HACK + if (APP->event->selectedWidget != this) + APP->event->setSelected(this); + } + else if (module->learnedCcs[id] >= 0) { + text = string::f("CC%d", module->learnedCcs[id]); + color.a = 1.0; + bgColor = nvgRGBA(0, 0, 0, 0); } else { text = "Unmapped"; color.a = 0.5; bgColor = nvgRGBA(0, 0, 0, 0); + + // HACK + if (APP->event->selectedWidget == this) + APP->event->setSelected(NULL); } } }; diff --git a/src/Core/plugin.hpp b/src/Core/plugin.hpp index 060b0eb1..db4a8cbe 100644 --- a/src/Core/plugin.hpp +++ b/src/Core/plugin.hpp @@ -87,6 +87,8 @@ struct CcChoice : LedDisplayChoice { else { text = string::f("%d", module->learnedCcs[id]); color.a = 1.0; + + // HACK if (APP->event->selectedWidget == this) APP->event->setSelected(NULL); } @@ -170,6 +172,7 @@ struct NoteChoice : LedDisplayChoice { text = string::f("%s%d", noteNames[semi], oct); color.a = 1.0; + // HACK if (APP->event->selectedWidget == this) APP->event->setSelected(NULL); }