midiInput.cpp (2748B)
1 #include "midiInput.h" 2 3 #include <array> 4 #include <cassert> 5 6 #include "portmidi/pm_common/portmidi.h" 7 8 #include <chrono> 9 10 #include "dsp56kEmu/logging.h" 11 12 #ifndef Pm_MessageData3 13 #define Pm_MessageData3(msg) (((msg) >> 24) & 0xFF) 14 #endif 15 16 PmTimestamp returnTimeProc(void*) 17 { 18 const auto now = std::chrono::system_clock::now().time_since_epoch(); 19 return static_cast<PmTimestamp>(std::chrono::duration_cast<std::chrono::milliseconds>(now).count()); 20 } 21 22 namespace mqConsoleLib 23 { 24 MidiInput::MidiInput(const std::string& _deviceName) : MidiDevice(_deviceName, false) 25 { 26 Device::openDevice(); 27 } 28 29 MidiInput::~MidiInput() 30 { 31 Pm_Close(m_stream); 32 m_stream = nullptr; 33 m_deviceId = -1; 34 } 35 36 int MidiInput::getDefaultDeviceId() const 37 { 38 return Pm_GetDefaultInputDeviceID(); 39 } 40 41 bool MidiInput::openDevice(int _devId) 42 { 43 const auto err = Pm_OpenInput(&m_stream, _devId, nullptr, 1024, returnTimeProc, this); 44 45 if(err != pmNoError) 46 { 47 LOG("Failed to open MIDI input device " << deviceNameFromId(_devId)); 48 m_stream = nullptr; 49 } 50 51 return err == pmNoError; 52 } 53 54 bool MidiInput::process(std::vector<synthLib::SMidiEvent>& _events) 55 { 56 if(!m_stream) 57 return false; 58 59 if(Pm_Poll(m_stream) == pmNoData) 60 return false; 61 62 while(true) 63 { 64 PmEvent e; 65 const auto count = Pm_Read(m_stream, &e, 1); 66 67 if(!count) 68 return false; 69 70 if(count != 1) 71 continue; 72 73 process(_events, e.message); 74 } 75 } 76 77 void MidiInput::process(std::vector<synthLib::SMidiEvent>& _events, uint32_t _message) 78 { 79 const uint8_t bytes[] = { 80 static_cast<uint8_t>(Pm_MessageStatus(_message)), 81 static_cast<uint8_t>(Pm_MessageData1(_message)), 82 static_cast<uint8_t>(Pm_MessageData2(_message)), 83 static_cast<uint8_t>(Pm_MessageData3(_message)) 84 }; 85 86 for (const auto byte : bytes) 87 { 88 if(byte == synthLib::M_STARTOFSYSEX) 89 { 90 assert(m_sysexBuffer.empty()); 91 m_readSysex = true; 92 m_sysexBuffer.push_back(byte); 93 } 94 else if(m_readSysex) 95 { 96 if(byte >= 0x80) 97 { 98 if(byte == synthLib::M_ENDOFSYSEX) 99 { 100 m_sysexBuffer.push_back(byte); 101 std::stringstream ss; 102 ss << HEXN(m_sysexBuffer.front(), 2); 103 for(size_t i=1; i<m_sysexBuffer.size(); ++i) 104 ss << ',' << HEXN(m_sysexBuffer[i], 2); 105 const std::string s(ss.str()); 106 LOG("Received sysex of size " << m_sysexBuffer.size() << ": " << s); 107 } 108 else 109 { 110 LOG("Received ABORTED sysex of size " << m_sysexBuffer.size()); 111 } 112 113 m_readSysex = false; 114 synthLib::SMidiEvent ev(synthLib::MidiEventSource::PhysicalInput); 115 std::swap(m_sysexBuffer, ev.sysex); 116 m_sysexBuffer.clear(); 117 _events.emplace_back(ev); 118 return; 119 } 120 121 m_sysexBuffer.push_back(byte); 122 } 123 } 124 125 if(!m_readSysex) 126 _events.emplace_back(synthLib::MidiEventSource::PhysicalInput, bytes[0], bytes[1], bytes[2]); 127 } 128 }