Line data Source code
1 : #include "GenericBLEMIDI_Interface.hpp" 2 : 3 : BEGIN_CS_NAMESPACE 4 : 5 : // -------------------------------------------------------------------------- // 6 : 7 : // The following section implements the MIDI sending functions. 8 : 9 : template <class BackendT> 10 : template <class L, class F> 11 18 : void GenericBLEMIDI_Interface<BackendT>::sendImpl(L &lck, F add_to_buffer) { 12 : // BLE packets are sent asynchronously, so we need a lock to access the 13 : // packet buffer 14 : // assert(lck.lck.owns_lock()); 15 : 16 : // Try adding the message to the current packet 17 18 : if (!add_to_buffer()) { 18 : // If that doesn't work, flush the packet (send it now and wait until 19 : // it is sent) 20 4 : backend.sendNow(lck); 21 : // And then add it to the (now emtpy) buffer 22 4 : add_to_buffer(); 23 : } 24 : // Notify the sending thread that data has been added to the buffer 25 18 : backend.releasePacketAndNotify(lck); 26 18 : } 27 : 28 : template <class BackendT> 29 11 : void GenericBLEMIDI_Interface<BackendT>::sendChannelMessageImpl( 30 : ChannelMessage msg) { 31 11 : uint16_t timestamp = millis(); // BLE MIDI timestamp 32 11 : auto lck = backend.acquirePacket(); 33 11 : if (msg.hasTwoDataBytes()) { 34 53 : sendImpl(lck, [&] { 35 45 : return lck.packet->add3B(msg.header, msg.data1, msg.data2, 36 9 : timestamp); 37 : }); 38 : } else { 39 19 : sendImpl(lck, [&] { 40 16 : return lck.packet->add2B(msg.header, msg.data1, timestamp); 41 : }); 42 : } 43 22 : } 44 : 45 : template <class BackendT> 46 4 : void GenericBLEMIDI_Interface<BackendT>::sendRealTimeImpl(RealTimeMessage msg) { 47 4 : uint16_t timestamp = millis(); // BLE MIDI timestamp 48 4 : auto lck = backend.acquirePacket(); 49 4 : sendImpl(lck, 50 5 : [&] { return lck.packet->addRealTime(msg.message, timestamp); }); 51 8 : } 52 : 53 : template <class BackendT> 54 3 : void GenericBLEMIDI_Interface<BackendT>::sendSysCommonImpl( 55 : SysCommonMessage msg) { 56 3 : uint16_t timestamp = millis(); // BLE MIDI timestamp 57 3 : auto lck = backend.acquirePacket(); 58 27 : sendImpl(lck, [&] { 59 16 : return lck.packet->addSysCommon(msg.getNumberOfDataBytes(), msg.header, 60 12 : msg.data1, msg.data2, timestamp); 61 : }); 62 6 : } 63 : 64 : template <class BackendT> 65 3 : void GenericBLEMIDI_Interface<BackendT>::sendSysExImpl(SysExMessage msg) { 66 3 : uint16_t timestamp = millis(); // BLE MIDI timestamp 67 3 : size_t length = msg.length; 68 3 : const uint8_t *data = msg.data; 69 : 70 : // BLE packets are sent asynchronously, so we need a lock to access the 71 : // packet buffer 72 3 : auto lck = backend.acquirePacket(); 73 : 74 : // TODO: I have no idea why, but the last byte gets cut off when the LSB 75 : // of the timestamp is 0x77 ... (Problem is probably in the BlueZ parser) 76 3 : if ((timestamp & 0x77) == 0x77) 77 0 : timestamp &= 0xFFFE; 78 : 79 : // Try adding at least the SysExStart header to the current packet 80 3 : if (!lck.packet->addSysEx(data, length, timestamp)) { 81 : // If that didn't fit, flush the packet 82 1 : backend.sendNow(lck); 83 : // Add the first part of the SysEx message to this packet 84 1 : lck.packet->addSysEx(data, length, timestamp); 85 : } 86 : // As long as there's data to be sent in the next packet 87 7 : while (data) { 88 : // Send the previous (full) packet 89 4 : backend.sendNow(lck); 90 : // And add the next part of the SysEx message to a continuation packet 91 4 : lck.packet->continueSysEx(data, length, timestamp); 92 : } 93 : // Notify the sending thread that data has been added to the buffer 94 3 : backend.releasePacketAndNotify(lck); 95 6 : } 96 : 97 : template <class BackendT> 98 12 : void GenericBLEMIDI_Interface<BackendT>::sendNowImpl() { 99 12 : auto lck = backend.acquirePacket(); 100 12 : backend.sendNow(lck); 101 24 : } 102 : 103 : // -------------------------------------------------------------------------- // 104 : 105 : template <class BackendT> 106 52 : MIDIReadEvent GenericBLEMIDI_Interface<BackendT>::read() { 107 : // Pop a new message from the queue 108 52 : if (!backend.popMessage(incomingMessage)) 109 12 : return MIDIReadEvent::NO_MESSAGE; 110 40 : return incomingMessage.eventType; 111 : } 112 : 113 : template <class BackendT> 114 33 : ChannelMessage GenericBLEMIDI_Interface<BackendT>::getChannelMessage() const { 115 33 : return incomingMessage.eventType == MIDIReadEvent::CHANNEL_MESSAGE 116 33 : ? incomingMessage.message.channelmessage 117 66 : : ChannelMessage(0, 0, 0); 118 : } 119 : 120 : template <class BackendT> 121 : SysCommonMessage 122 1 : GenericBLEMIDI_Interface<BackendT>::getSysCommonMessage() const { 123 1 : return incomingMessage.eventType == MIDIReadEvent::SYSCOMMON_MESSAGE 124 1 : ? incomingMessage.message.syscommonmessage 125 2 : : SysCommonMessage(0, 0, 0); 126 : } 127 : 128 : template <class BackendT> 129 2 : RealTimeMessage GenericBLEMIDI_Interface<BackendT>::getRealTimeMessage() const { 130 2 : return incomingMessage.eventType == MIDIReadEvent::REALTIME_MESSAGE 131 2 : ? incomingMessage.message.realtimemessage 132 4 : : RealTimeMessage(0); 133 : } 134 : 135 : template <class BackendT> 136 8 : SysExMessage GenericBLEMIDI_Interface<BackendT>::getSysExMessage() const { 137 8 : auto evt = incomingMessage.eventType; 138 8 : bool hasSysEx = evt == MIDIReadEvent::SYSEX_MESSAGE || 139 : evt == MIDIReadEvent::SYSEX_CHUNK; 140 8 : return hasSysEx ? incomingMessage.message.sysexmessage 141 16 : : SysExMessage(nullptr, 0); 142 : } 143 : 144 : template <class BackendT> 145 13 : uint16_t GenericBLEMIDI_Interface<BackendT>::getTimestamp() const { 146 13 : return incomingMessage.timestamp; 147 : } 148 : 149 : // -------------------------------------------------------------------------- // 150 : 151 : template <class BackendT> 152 : void GenericBLEMIDI_Interface<BackendT>::setName(const char *name) { 153 : ble_settings.device_name = name; 154 : } 155 : 156 : template <class BackendT> 157 28 : void GenericBLEMIDI_Interface<BackendT>::begin() { 158 28 : backend.begin(ble_settings); 159 28 : } 160 : 161 : template <class BackendT> 162 : void GenericBLEMIDI_Interface<BackendT>::end() { 163 : backend.end(); 164 : } 165 : 166 : // -------------------------------------------------------------------------- // 167 : 168 : END_CS_NAMESPACE