diff --git a/src/core/MidiClockToCV.cpp b/src/core/MidiClockToCV.cpp index 57722157..e1caab0e 100644 --- a/src/core/MidiClockToCV.cpp +++ b/src/core/MidiClockToCV.cpp @@ -35,7 +35,6 @@ struct MIDIClockToCVInterface : MidiIO, Module { MIDIClockToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { - ignore_midiTime = false; } @@ -46,9 +45,11 @@ struct MIDIClockToCVInterface : MidiIO, Module { void processMidi(std::vector msg); - virtual void resetMidi(); + void onDeviceChange(); - virtual json_t *toJson() { + void resetMidi(); + + json_t *toJson() { json_t *rootJ = json_object(); addBaseJson(rootJ); json_object_set_new(rootJ, "clock1ratio", json_integer(clock1ratio)); @@ -56,7 +57,7 @@ struct MIDIClockToCVInterface : MidiIO, Module { return rootJ; } - virtual void fromJson(json_t *rootJ) { + void fromJson(json_t *rootJ) { baseFromJson(rootJ); json_t *c1rJ = json_object_get(rootJ, "clock1ratio"); if (c1rJ) { @@ -69,7 +70,7 @@ struct MIDIClockToCVInterface : MidiIO, Module { } } - virtual void initialize() { + void initialize() { resetMidi(); } @@ -178,6 +179,10 @@ void MIDIClockToCVInterface::processMidi(std::vector msg) { } +void MIDIClockToCVInterface::onDeviceChange() { + setIgnores(true, false); +} + struct ClockRatioItem : MenuItem { int ratio; int *clockRatio; diff --git a/src/core/MidiInterface.cpp b/src/core/MidiInterface.cpp index 490f07f4..6183df29 100644 --- a/src/core/MidiInterface.cpp +++ b/src/core/MidiInterface.cpp @@ -7,7 +7,6 @@ using namespace rack; - /** * MidiIO implements the shared functionality of all midi modules, namely: * + Channel Selection (including helper for storing json) @@ -27,7 +26,7 @@ void MidiIO::setChannel(int channel) { this->channel = channel; } -std::unordered_map MidiIO::midiInMap = {}; +std::unordered_map MidiIO::midiInMap = {}; json_t *MidiIO::addBaseJson(json_t *rootJ) { if (deviceName != "") { @@ -51,7 +50,7 @@ void MidiIO::baseFromJson(json_t *rootJ) { std::vector MidiIO::getDevices() { /* Note: we could also use an existing interface if one exists */ - static RtMidiIn * m = new RtMidiIn(); + static RtMidiIn *m = new RtMidiIn(); std::vector names = {}; @@ -85,20 +84,34 @@ void MidiIO::openDevice(std::string deviceName) { } catch (RtMidiError &error) { fprintf(stderr, "Failed to create RtMidiIn: %s\n", error.getMessage().c_str()); + this->deviceName = ""; + this->id = -1; return; } } this->deviceName = deviceName; - /* TODO: this works for now, but is not ideal. If a clock is added and connected to a module - * the time messages will still be received after the clock is removed. This adds an overhead - * which can be avoided but I want to find a good solution.*/ - if (!ignore_midiTime || !ignore_midiTime || !ignore_midiSense){ - midiInMap[deviceName]->ignoreTypes(ignore_midiSysex, ignore_midiTime, ignore_midiSense); + id = midiInMap[deviceName]->add(); + onDeviceChange(); +} + +void MidiIO::setIgnores(bool ignoreSysex, bool ignoreTime, bool ignoreSense) { + bool sy = true, ti = true, se = true; + + midiInMap[deviceName]->ignoresMap[id][0] = ignoreSysex; + midiInMap[deviceName]->ignoresMap[id][1] = ignoreTime; + midiInMap[deviceName]->ignoresMap[id][2] = ignoreSense; + + for (auto kv : midiInMap[deviceName]->ignoresMap) { + sy = sy && kv.second[0]; + ti = ti && kv.second[1]; + se = se && kv.second[2]; } - id = midiInMap[deviceName]->add(); + midiInMap[deviceName]->ignoreTypes(se,ti,se); + + } std::string MidiIO::getDeviceName() { @@ -141,13 +154,15 @@ bool MidiIO::isPortOpen() { void MidiIO::close() { - MidiInWrapper * mw = midiInMap[deviceName]; + MidiInWrapper *mw = midiInMap[deviceName]; if (!mw || id < 0) { //fprintf(stderr, "Trying to close already closed device!\n"); return; } + setIgnores(); // reset ignore types for this instance + mw->erase(id); if (mw->subscribers == 0) { diff --git a/src/core/MidiInterface.hpp b/src/core/MidiInterface.hpp index 964b3645..c88287e4 100644 --- a/src/core/MidiInterface.hpp +++ b/src/core/MidiInterface.hpp @@ -15,6 +15,12 @@ using namespace rack; struct MidiInWrapper : RtMidiIn { std::unordered_map>> idMessagesMap; std::unordered_map> idStampsMap; + + /* Stores Ignore settings for each instance in the following order: + * {ignore_midiSysex, ignore_midiTime, ignore_midiSense} + */ + std::unordered_map ignoresMap; + int uid_c = 0; int subscribers = 0; @@ -28,6 +34,10 @@ struct MidiInWrapper : RtMidiIn { subscribers++; idMessagesMap[id] = {}; idStampsMap[id] = {}; + + ignoresMap[id][0] = true; + ignoresMap[id][1] = true; + ignoresMap[id][2] = true; return id; } @@ -35,6 +45,7 @@ struct MidiInWrapper : RtMidiIn { subscribers--; idMessagesMap.erase(id); idStampsMap.erase(id); + ignoresMap.erase(id); } }; @@ -47,9 +58,6 @@ private: bool isOut = false; public: - bool ignore_midiSysex=true; - bool ignore_midiTime=true; - bool ignore_midiSense=true; int channel; @@ -63,6 +71,8 @@ public: void openDevice(std::string deviceName); + void setIgnores(bool ignoreSysex = true, bool ignoreTime = true, bool ignoreSense = true); + std::string getDeviceName(); void setChannel(int channel); @@ -79,6 +89,9 @@ public: /* called when midi port is set */ virtual void resetMidi()=0; + + /* called if a user switches or sets the deivce (and after this device is initialised)*/ + virtual void onDeviceChange(){}; }; //////////////////////