|
|
@@ -16,11 +16,21 @@ struct MIDI_Map : Module { |
|
|
|
}; |
|
|
|
|
|
|
|
midi::InputQueue midiInput; |
|
|
|
/** Channel ID of the learning session */ |
|
|
|
int learningId; |
|
|
|
/** Whether the CC has been set during the learning session */ |
|
|
|
bool learnedCc; |
|
|
|
/** Whether the param has been set during the learning session */ |
|
|
|
bool learnedParam; |
|
|
|
/** The learned CC number of each channel */ |
|
|
|
int learnedCcs[8]; |
|
|
|
/** The learned module handle of each channel */ |
|
|
|
ModuleHandle learnedModuleHandles[8]; |
|
|
|
/** The learned param ID of each channel */ |
|
|
|
int learnedParamIds[8]; |
|
|
|
/** The value of each CC number */ |
|
|
|
int8_t values[128]; |
|
|
|
/** The smoothing processor (normalized between 0 and 1) of each channel */ |
|
|
|
dsp::ExponentialFilter valueFilters[8]; |
|
|
|
|
|
|
|
MIDI_Map() { |
|
|
@@ -39,6 +49,8 @@ struct MIDI_Map : Module { |
|
|
|
|
|
|
|
void onReset() override { |
|
|
|
learningId = -1; |
|
|
|
learnedCc = false; |
|
|
|
learnedParam = false; |
|
|
|
for (int i = 0; i < 8; i++) { |
|
|
|
learnedCcs[i] = -1; |
|
|
|
unloadModuleHandle(i); |
|
|
@@ -71,6 +83,7 @@ struct MIDI_Map : Module { |
|
|
|
learnedModuleHandles[learningId].id = module->id; |
|
|
|
loadModuleHandle(learningId); |
|
|
|
learnedParamIds[learningId] = paramId; |
|
|
|
learnedParam = true; |
|
|
|
commitLearn(); |
|
|
|
} |
|
|
|
} |
|
|
@@ -115,6 +128,8 @@ struct MIDI_Map : Module { |
|
|
|
// Learn |
|
|
|
if (learningId >= 0 && values[cc] != msg.getValue()) { |
|
|
|
learnedCcs[learningId] = cc; |
|
|
|
valueFilters[learningId].reset(); |
|
|
|
learnedCc = true; |
|
|
|
commitLearn(); |
|
|
|
} |
|
|
|
values[cc] = msg.getValue(); |
|
|
@@ -135,22 +150,45 @@ struct MIDI_Map : Module { |
|
|
|
void commitLearn() { |
|
|
|
if (learningId < 0) |
|
|
|
return; |
|
|
|
if (learnedModuleHandles[learningId].id < 0) |
|
|
|
if (!learnedCc) |
|
|
|
return; |
|
|
|
if (learnedCcs[learningId] < 0) |
|
|
|
if (!learnedParam) |
|
|
|
return; |
|
|
|
learningId++; |
|
|
|
if (learningId >= 8) |
|
|
|
learningId = -1; |
|
|
|
// Reset learned state |
|
|
|
learnedCc = false; |
|
|
|
learnedParam = false; |
|
|
|
// Find next unlearned channel |
|
|
|
while (++learningId < 8) { |
|
|
|
if (learnedCcs[learningId] < 0 || learnedModuleHandles[learningId].id < 0) |
|
|
|
return; |
|
|
|
} |
|
|
|
learningId = -1; |
|
|
|
} |
|
|
|
|
|
|
|
void clearLearn(int id) { |
|
|
|
disableLearn(id); |
|
|
|
learnedCcs[id] = -1; |
|
|
|
unloadModuleHandle(id); |
|
|
|
learnedModuleHandles[id].id = -1; |
|
|
|
loadModuleHandle(id); |
|
|
|
} |
|
|
|
|
|
|
|
void enableLearn(int id) { |
|
|
|
if (learningId != id) { |
|
|
|
learningId = id; |
|
|
|
learnedCc = false; |
|
|
|
learnedParam = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void disableLearn(int id) { |
|
|
|
if (learningId == id) { |
|
|
|
learningId = -1; |
|
|
|
learnedCc = false; |
|
|
|
learnedParam = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
json_t *dataToJson() override { |
|
|
|
json_t *rootJ = json_object(); |
|
|
|
|
|
|
@@ -231,27 +269,28 @@ struct MIDI_MapChoice : LedDisplayChoice { |
|
|
|
if (module) { |
|
|
|
module->clearLearn(id); |
|
|
|
} |
|
|
|
e.consume(this); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void onSelect(const event::Select &e) override { |
|
|
|
if (!module) |
|
|
|
return; |
|
|
|
module->learningId = id; |
|
|
|
module->enableLearn(id); |
|
|
|
e.consume(this); |
|
|
|
} |
|
|
|
|
|
|
|
void onDeselect(const event::Deselect &e) override { |
|
|
|
if (!module) |
|
|
|
return; |
|
|
|
if (module->learningId == id) { |
|
|
|
module->learningId = -1; |
|
|
|
} |
|
|
|
module->disableLearn(id); |
|
|
|
} |
|
|
|
|
|
|
|
void step() override { |
|
|
|
if (!module) |
|
|
|
return; |
|
|
|
|
|
|
|
// Set bgColor and selected state |
|
|
|
if (module->learningId == id) { |
|
|
|
bgColor = color; |
|
|
|
bgColor.a = 0.15; |
|
|
@@ -264,27 +303,35 @@ struct MIDI_MapChoice : LedDisplayChoice { |
|
|
|
bgColor = nvgRGBA(0, 0, 0, 0); |
|
|
|
|
|
|
|
// HACK |
|
|
|
// Don't let the event state call onDeselect() |
|
|
|
if (APP->event->selectedWidget == this) |
|
|
|
APP->event->setSelected(NULL); |
|
|
|
} |
|
|
|
|
|
|
|
// Set text |
|
|
|
text = ""; |
|
|
|
color.a = 1.0; |
|
|
|
if (module->learnedCcs[id] >= 0) { |
|
|
|
text += string::f("CC%d ", module->learnedCcs[id]); |
|
|
|
} |
|
|
|
if (module->learnedModuleHandles[id].id >= 0) { |
|
|
|
text += getParamName(); |
|
|
|
} |
|
|
|
if (!(module->learnedCcs[id] >= 0) && !(module->learnedModuleHandles[id].id >= 0)) { |
|
|
|
if (module->learnedCcs[id] < 0 && module->learnedModuleHandles[id].id < 0) { |
|
|
|
if (module->learningId == id) { |
|
|
|
text = "Mapping..."; |
|
|
|
} |
|
|
|
else { |
|
|
|
text = "Unmapped"; |
|
|
|
color.a = 0.5; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Set text color |
|
|
|
if ((module->learnedCcs[id] >= 0 && module->learnedModuleHandles[id].id >= 0) || module->learningId == id) { |
|
|
|
color.a = 1.0; |
|
|
|
} |
|
|
|
else { |
|
|
|
color.a = 0.5; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
std::string getParamName() { |
|
|
|