Line data Source code
1 : #include "MIDI_Interface.hpp" 2 : 3 : BEGIN_CS_NAMESPACE 4 : 5 96 : MIDI_Interface::~MIDI_Interface() { 6 96 : if (getDefault() == this) 7 96 : DefaultMIDI_Interface = nullptr; 8 96 : } 9 : 10 : MIDI_Interface *MIDI_Interface::DefaultMIDI_Interface = nullptr; 11 : 12 0 : void MIDI_Interface::setAsDefault() { DefaultMIDI_Interface = this; } 13 : 14 131 : MIDI_Interface *MIDI_Interface::getDefault() { 15 : #ifndef ARDUINO 16 262 : return DefaultMIDI_Interface == nullptr 17 131 : ? dynamic_cast<MIDI_Interface *>(updatables.getLast()) 18 0 : : DefaultMIDI_Interface; 19 : #else 20 : return DefaultMIDI_Interface == nullptr 21 : ? static_cast<MIDI_Interface *>(updatables.getLast()) 22 : : DefaultMIDI_Interface; 23 : #endif 24 : } 25 : 26 : // -------------------------------- SENDING --------------------------------- // 27 : 28 106 : void MIDI_Interface::sinkMIDIfromPipe(ChannelMessage msg) { send(msg); } 29 5 : void MIDI_Interface::sinkMIDIfromPipe(SysExMessage msg) { send(msg); } 30 2 : void MIDI_Interface::sinkMIDIfromPipe(RealTimeMessage msg) { send(msg); } 31 : 32 : // -------------------------------- READING --------------------------------- // 33 : 34 10 : void Parsing_MIDI_Interface::update() { 35 10 : if (event == MIDIReadEvent::NO_MESSAGE) // If previous event was handled 36 8 : event = read(); // Read the next incoming message 37 17 : while (event != MIDIReadEvent::NO_MESSAGE) { // As long as there are 38 : // incoming messages 39 9 : if (dispatchMIDIEvent(event)) // If event was handled successfully 40 7 : event = read(); // Read the next incoming message 41 : else // If pipe is locked 42 2 : break; // Try sending again next time 43 : } 44 : // TODO: maximum number of iterations? Timeout? 45 10 : } 46 : 47 70 : bool Parsing_MIDI_Interface::dispatchMIDIEvent(MIDIReadEvent event) { 48 70 : switch (event) { 49 42 : case MIDIReadEvent::NO_MESSAGE: return true; 50 16 : case MIDIReadEvent::CHANNEL_MESSAGE: return onChannelMessage(); 51 9 : case MIDIReadEvent::SYSEX_MESSAGE: return onSysExMessage(); 52 3 : case MIDIReadEvent::REALTIME_MESSAGE: return onRealTimeMessage(); 53 0 : default: return true; 54 : } 55 70 : } 56 : 57 3 : bool Parsing_MIDI_Interface::onRealTimeMessage() { 58 : // Always send write to pipe, don't check if it's in exclusive mode or not 59 3 : auto message = getRealTimeMessage(); 60 3 : sourceMIDItoPipe(message); 61 3 : if (callbacks) 62 2 : callbacks->onRealTimeMessage(*this); 63 3 : return true; 64 3 : } 65 : 66 16 : bool Parsing_MIDI_Interface::onChannelMessage() { 67 16 : auto message = getChannelMessage(); 68 16 : if (!canWrite(message.CN)) 69 1 : return false; 70 15 : sourceMIDItoPipe(message); 71 15 : if (callbacks) 72 13 : callbacks->onChannelMessage(*this); 73 : // TODO: we have the message already, should we just pass it to the 74 : // callback as a parameter? (idem for SysEx and RT) 75 15 : return true; 76 16 : } 77 : 78 9 : bool Parsing_MIDI_Interface::onSysExMessage() { 79 9 : auto message = getSysExMessage(); 80 9 : if (!canWrite(message.CN)) 81 1 : return false; 82 8 : sourceMIDItoPipe(message); 83 8 : if (callbacks) 84 5 : callbacks->onSysExMessage(*this); 85 8 : return true; 86 9 : } 87 : 88 : END_CS_NAMESPACE