Line data Source code
1 : #if defined(ESP32) || !defined(ARDUINO) 2 : 3 : #include "MIDIMessageQueue.hpp" 4 : 5 : BEGIN_CS_NAMESPACE 6 : 7 4 : MIDIMessageQueue::MIDIMessageQueueElement::MIDIMessageQueueElement( 8 4 : SysExMessage message, uint16_t timestamp) 9 4 : : eventType(message.isLastChunk() ? MIDIReadEvent::SYSEX_MESSAGE 10 : : MIDIReadEvent::SYSEX_CHUNK), 11 4 : message(message), timestamp(timestamp) { 12 : // SysEx data is copied, not stored by pointer, so allocate new 13 : // storage for the SysEx data, and copy it if allocation was 14 : // successful. 15 4 : uint8_t *newBuffer = new uint8_t[message.length]; 16 : // Make sure that allocation was successful. 17 4 : if (newBuffer == nullptr) { 18 : DEBUGREF(F("SysEx buffer allocation failed")); 19 0 : this->eventType = MIDIReadEvent::NO_MESSAGE; 20 0 : this->message.realtimemessage = 0x00; 21 : } else { 22 : // Copy the SysEx data to the newly allocated buffer 23 4 : memcpy(newBuffer, message.data, message.length); 24 4 : this->message.sysexmessage.data = newBuffer; 25 : } 26 4 : } 27 : 28 0 : MIDIMessageQueue::MIDIMessageQueueElement::MIDIMessageQueueElement( 29 0 : MIDIMessageQueue::MIDIMessageQueueElement &&that) { 30 0 : *this = std::move(that); 31 0 : } 32 : 33 : MIDIMessageQueue::MIDIMessageQueueElement & 34 46 : MIDIMessageQueue::MIDIMessageQueueElement::operator=( 35 : MIDIMessageQueue::MIDIMessageQueueElement &&that) { 36 46 : std::swap(this->eventType, that.eventType); 37 46 : std::swap(this->message, that.message); 38 46 : std::swap(this->timestamp, that.timestamp); 39 46 : return *this; 40 : } 41 : 42 1866 : void MIDIMessageQueue::MIDIMessageQueueElement::release() { 43 1866 : if (eventType == MIDIReadEvent::SYSEX_CHUNK || 44 1866 : eventType == MIDIReadEvent::SYSEX_MESSAGE) { 45 4 : delete[] message.sysexmessage.data; 46 4 : message.sysexmessage.data = nullptr; 47 4 : message.sysexmessage.length = 0; 48 4 : eventType = MIDIReadEvent::NO_MESSAGE; 49 4 : message.realtimemessage = 0x00; 50 : } 51 1866 : } 52 : 53 16 : bool MIDIMessageQueue::push(ChannelMessage message, uint16_t timestamp) { 54 16 : return push(MIDIMessageQueueElement(message, timestamp)); 55 : } 56 : 57 1 : bool MIDIMessageQueue::push(SysCommonMessage message, uint16_t timestamp) { 58 1 : return push(MIDIMessageQueueElement(message, timestamp)); 59 : } 60 : 61 2 : bool MIDIMessageQueue::push(RealTimeMessage message, uint16_t timestamp) { 62 2 : return push(MIDIMessageQueueElement(message, timestamp)); 63 : } 64 : 65 4 : bool MIDIMessageQueue::push(SysExMessage message, uint16_t timestamp) { 66 8 : if (storage.size() == size.load(std::memory_order_acquire)) 67 0 : return false; 68 : 69 : // Allocate storage for the actual SysEx data and copy the data 70 8 : MIDIMessageQueueElement el(message, timestamp); 71 : // Check if allocation failed 72 4 : if (el.eventType == MIDIReadEvent::NO_MESSAGE) 73 0 : return true; // TODO: should we try again later? 74 : 75 4 : *write_p = std::move(el); 76 4 : inc(write_p); 77 4 : size.fetch_add(1, std::memory_order_release); 78 : 79 4 : return true; 80 : } 81 : 82 34 : bool MIDIMessageQueue::pop(MIDIMessageQueueElement &message) { 83 68 : if (size.load(std::memory_order_acquire) == 0) 84 11 : return false; 85 23 : message = std::move(*read_p); 86 23 : read_p->release(); // release memory of old message 87 23 : inc(read_p); 88 23 : size.fetch_sub(1, std::memory_order_release); 89 23 : return true; 90 : } 91 : 92 19 : bool MIDIMessageQueue::push(MIDIMessageQueueElement &&message) { 93 38 : if (storage.size() == size.load(std::memory_order_acquire)) 94 0 : return false; 95 19 : *write_p = std::move(message); 96 19 : inc(write_p); 97 19 : size.fetch_add(1, std::memory_order_release); 98 19 : return true; 99 : } 100 : 101 : END_CS_NAMESPACE 102 : 103 : #endif