|
|
@@ -0,0 +1,154 @@ |
|
|
|
/* |
|
|
|
* DISTRHO Cardinal Plugin |
|
|
|
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> |
|
|
|
* |
|
|
|
* This program is free software; you can redistribute it and/or |
|
|
|
* modify it under the terms of the GNU General Public License as |
|
|
|
* published by the Free Software Foundation; either version 3 of |
|
|
|
* the License, or any later version. |
|
|
|
* |
|
|
|
* This program is distributed in the hope that it will be useful, |
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
* GNU General Public License for more details. |
|
|
|
* |
|
|
|
* For a full copy of the GNU General Public License see the LICENSE file. |
|
|
|
*/ |
|
|
|
|
|
|
|
/** |
|
|
|
* This file is an edited version of VCVRack's MIDI_CV.cpp |
|
|
|
* Copyright (C) 2016-2021 VCV. |
|
|
|
* |
|
|
|
* This program is free software: you can redistribute it and/or |
|
|
|
* modify it under the terms of the GNU General Public License as |
|
|
|
* published by the Free Software Foundation; either version 3 of |
|
|
|
* the License, or (at your option) any later version. |
|
|
|
*/ |
|
|
|
|
|
|
|
#include "../Rack/src/core/MIDI_CV.cpp" |
|
|
|
|
|
|
|
#include <nanosvg.h> |
|
|
|
|
|
|
|
namespace rack { |
|
|
|
namespace core { |
|
|
|
|
|
|
|
static inline void nsvg__deletePaths(NSVGpath* path) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
struct MIDI_CVWidget_Cardinal : ModuleWidget |
|
|
|
{ |
|
|
|
MIDI_CV* const module; |
|
|
|
|
|
|
|
MIDI_CVWidget_Cardinal(MIDI_CV* const m) |
|
|
|
: module(m) |
|
|
|
{ |
|
|
|
setModule(module); |
|
|
|
|
|
|
|
std::shared_ptr<Svg> svg(Svg::load(asset::system("res/Core/MIDI_CV.svg"))); |
|
|
|
|
|
|
|
// this section removes the CLK and CLK/N part of the svg |
|
|
|
for (NSVGshape *shape = svg->handle->shapes, *old = nullptr; shape != nullptr;) |
|
|
|
{ |
|
|
|
if (std::strcmp(shape->id, "rect22") != 0 && |
|
|
|
std::strcmp(shape->id, "rect20") != 0 && |
|
|
|
std::strcmp(shape->id, "path97") != 0 && |
|
|
|
std::strcmp(shape->id, "path99") != 0 && |
|
|
|
std::strcmp(shape->id, "path101") != 0 && |
|
|
|
std::strcmp(shape->id, "path85") != 0 && |
|
|
|
std::strcmp(shape->id, "path87") != 0 && |
|
|
|
std::strcmp(shape->id, "path89") != 0 && |
|
|
|
std::strcmp(shape->id, "path91") != 0 && |
|
|
|
std::strcmp(shape->id, "path93") != 0) |
|
|
|
{ |
|
|
|
old = shape; |
|
|
|
shape = shape->next; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
NSVGshape* const next = shape->next; |
|
|
|
|
|
|
|
for (NSVGpath* path = shape->paths; path != nullptr;) |
|
|
|
{ |
|
|
|
NSVGpath* next = path->next; |
|
|
|
std::free(path->pts); |
|
|
|
std::free(path); |
|
|
|
path = next; |
|
|
|
} |
|
|
|
|
|
|
|
std::free(shape); |
|
|
|
|
|
|
|
shape = next; |
|
|
|
|
|
|
|
if (old != nullptr) |
|
|
|
old->next = next; |
|
|
|
else |
|
|
|
svg->handle->shapes = next; |
|
|
|
} |
|
|
|
|
|
|
|
setPanel(svg); |
|
|
|
|
|
|
|
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); |
|
|
|
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); |
|
|
|
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); |
|
|
|
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); |
|
|
|
|
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.905, 64.347)), module, MIDI_CV::PITCH_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(20.248, 64.347)), module, MIDI_CV::GATE_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(32.591, 64.347)), module, MIDI_CV::VELOCITY_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.905, 80.603)), module, MIDI_CV::AFTERTOUCH_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(20.248, 80.603)), module, MIDI_CV::PW_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(32.591, 80.603)), module, MIDI_CV::MOD_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(32.591, 96.859)), module, MIDI_CV::RETRIGGER_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.905, 113.115)), module, MIDI_CV::START_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(20.248, 113.115)), module, MIDI_CV::STOP_OUTPUT)); |
|
|
|
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(32.591, 112.975)), module, MIDI_CV::CONTINUE_OUTPUT)); |
|
|
|
|
|
|
|
MidiDisplay* display = createWidget<MidiDisplay>(mm2px(Vec(0.0, 13.048))); |
|
|
|
display->box.size = mm2px(Vec(40.64, 29.012)); |
|
|
|
display->setMidiPort(m != nullptr ? &m->midiInput : nullptr); |
|
|
|
addChild(display); |
|
|
|
} |
|
|
|
|
|
|
|
void appendContextMenu(Menu* const menu) override |
|
|
|
{ |
|
|
|
menu->addChild(new MenuSeparator); |
|
|
|
|
|
|
|
menu->addChild(createBoolPtrMenuItem("Smooth pitch/mod wheel", "", &module->smooth)); |
|
|
|
|
|
|
|
struct ChannelItem : MenuItem { |
|
|
|
MIDI_CV* module; |
|
|
|
Menu* createChildMenu() override { |
|
|
|
Menu* menu = new Menu; |
|
|
|
for (int c = 1; c <= 16; c++) { |
|
|
|
menu->addChild(createCheckMenuItem((c == 1) ? "Monophonic" : string::f("%d", c), "", |
|
|
|
[=]() {return module->channels == c;}, |
|
|
|
[=]() {module->setChannels(c);} |
|
|
|
)); |
|
|
|
} |
|
|
|
return menu; |
|
|
|
} |
|
|
|
}; |
|
|
|
ChannelItem* channelItem = new ChannelItem; |
|
|
|
channelItem->text = "Polyphony channels"; |
|
|
|
channelItem->rightText = string::f("%d", module->channels) + " " + RIGHT_ARROW; |
|
|
|
channelItem->module = module; |
|
|
|
menu->addChild(channelItem); |
|
|
|
|
|
|
|
menu->addChild(createIndexPtrSubmenuItem("Polyphony mode", { |
|
|
|
"Rotate", |
|
|
|
"Reuse", |
|
|
|
"Reset", |
|
|
|
"MPE", |
|
|
|
}, &module->polyMode)); |
|
|
|
|
|
|
|
menu->addChild(createMenuItem("Panic", "", |
|
|
|
[=]() {module->panic();} |
|
|
|
)); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
Model* modelMIDI_CV_Cardinal = createModel<MIDI_CV, MIDI_CVWidget_Cardinal>("MIDIToCVInterface"); |
|
|
|
|
|
|
|
} |
|
|
|
} |