added send(MidiMessage), added (untested) bridge example
added send(MidiMessage) for Bridge application (that convert MIDI transport x into MIDI transport y), avoiding parsing entry a stream, setting up all callback - whilst this allows for passing the content, without to much processing/parsing. Had to move mPendingMessageExpectedLenght into MidiMessage to avoid parsing the data again, just to know the size Added Bridge example (untested)
This commit is contained in:
		
							parent
							
								
									8905d36c0e
								
							
						
					
					
						commit
						8893642b27
					
				|  | @ -0,0 +1,34 @@ | ||||||
|  | #include <MIDI.h> | ||||||
|  | #include <USB-MIDI.h> | ||||||
|  | 
 | ||||||
|  | MIDI_CREATE_INSTANCE(HardwareSerial, Serial1,  MIDI1); | ||||||
|  | USBMIDI_CREATE_DEFAULT_INSTANCE(); | ||||||
|  | 
 | ||||||
|  | void handleMessage1(TypedMidiInterface::MidiMessage message) | ||||||
|  | { | ||||||
|  |     MIDI.sendMessage(message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void handleMessage(TypedMidiInterface::MidiMessage message) | ||||||
|  | { | ||||||
|  |     MIDI1.sendMessage(message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // -----------------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | void setup() | ||||||
|  | { | ||||||
|  |     MIDI.setHandleMessage(handleMessage); | ||||||
|  |     MIDI1.setHandleMessage(handleMessage1); | ||||||
|  | 
 | ||||||
|  |     // Initiate MIDI communications, listen to all channels
 | ||||||
|  |     MIDI.begin(MIDI_CHANNEL_OMNI); | ||||||
|  |     MIDI1.begin(MIDI_CHANNEL_OMNI); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void loop() | ||||||
|  | { | ||||||
|  |     // Call MIDI.read the fastest you can for real-time performance.
 | ||||||
|  |     MIDI.read(); | ||||||
|  |     MIDI1.read(); | ||||||
|  | } | ||||||
|  | @ -24,11 +24,6 @@ void handleNoteOff(byte channel, byte pitch, byte velocity) | ||||||
|     // Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
 |     // Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void handleMessage(__mismt::MidiMessage message) |  | ||||||
| { |  | ||||||
|     // Do something when the message.
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // -----------------------------------------------------------------------------
 | // -----------------------------------------------------------------------------
 | ||||||
| 
 | 
 | ||||||
| void setup() | void setup() | ||||||
|  | @ -40,8 +35,6 @@ void setup() | ||||||
|     // Do the same for NoteOffs
 |     // Do the same for NoteOffs
 | ||||||
|     MIDI.setHandleNoteOff(handleNoteOff); |     MIDI.setHandleNoteOff(handleNoteOff); | ||||||
| 
 | 
 | ||||||
|     MIDI.setHandleMessage(handleMessage); |  | ||||||
| 
 |  | ||||||
|     // Initiate MIDI communications, listen to all channels
 |     // Initiate MIDI communications, listen to all channels
 | ||||||
|     MIDI.begin(MIDI_CHANNEL_OMNI); |     MIDI.begin(MIDI_CHANNEL_OMNI); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -130,6 +130,8 @@ public: | ||||||
|                                   Channel inChannel); |                                   Channel inChannel); | ||||||
|     inline void endNrpn(Channel inChannel); |     inline void endNrpn(Channel inChannel); | ||||||
| 
 | 
 | ||||||
|  |     inline void send(MidiMessage); | ||||||
|  |      | ||||||
| public: | public: | ||||||
|     void send(MidiType inType, |     void send(MidiType inType, | ||||||
|               DataByte inData1, |               DataByte inData1, | ||||||
|  | @ -239,7 +241,6 @@ private: | ||||||
|     StatusByte      mRunningStatus_RX; |     StatusByte      mRunningStatus_RX; | ||||||
|     StatusByte      mRunningStatus_TX; |     StatusByte      mRunningStatus_TX; | ||||||
|     byte            mPendingMessage[3]; |     byte            mPendingMessage[3]; | ||||||
|     unsigned        mPendingMessageExpectedLenght; |  | ||||||
|     unsigned        mPendingMessageIndex; |     unsigned        mPendingMessageIndex; | ||||||
|     unsigned        mCurrentRpnNumber; |     unsigned        mCurrentRpnNumber; | ||||||
|     unsigned        mCurrentNrpnNumber; |     unsigned        mCurrentNrpnNumber; | ||||||
|  |  | ||||||
							
								
								
									
										62
									
								
								src/MIDI.hpp
								
								
								
								
							
							
						
						
									
										62
									
								
								src/MIDI.hpp
								
								
								
								
							|  | @ -36,7 +36,6 @@ inline MidiInterface<Transport, Settings, Platform>::MidiInterface(Transport& in | ||||||
|     , mInputChannel(0) |     , mInputChannel(0) | ||||||
|     , mRunningStatus_RX(InvalidType) |     , mRunningStatus_RX(InvalidType) | ||||||
|     , mRunningStatus_TX(InvalidType) |     , mRunningStatus_TX(InvalidType) | ||||||
|     , mPendingMessageExpectedLenght(0) |  | ||||||
|     , mPendingMessageIndex(0) |     , mPendingMessageIndex(0) | ||||||
|     , mCurrentRpnNumber(0xffff) |     , mCurrentRpnNumber(0xffff) | ||||||
|     , mCurrentNrpnNumber(0xffff) |     , mCurrentNrpnNumber(0xffff) | ||||||
|  | @ -94,7 +93,6 @@ void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel) | ||||||
|     mRunningStatus_RX = InvalidType; |     mRunningStatus_RX = InvalidType; | ||||||
| 
 | 
 | ||||||
|     mPendingMessageIndex = 0; |     mPendingMessageIndex = 0; | ||||||
|     mPendingMessageExpectedLenght = 0; |  | ||||||
| 
 | 
 | ||||||
|     mCurrentRpnNumber  = 0xffff; |     mCurrentRpnNumber  = 0xffff; | ||||||
|     mCurrentNrpnNumber = 0xffff; |     mCurrentNrpnNumber = 0xffff; | ||||||
|  | @ -107,6 +105,7 @@ void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel) | ||||||
|     mMessage.channel = 0; |     mMessage.channel = 0; | ||||||
|     mMessage.data1   = 0; |     mMessage.data1   = 0; | ||||||
|     mMessage.data2   = 0; |     mMessage.data2   = 0; | ||||||
|  |     mMessage.length  = 0; | ||||||
| 
 | 
 | ||||||
|     mThruFilterMode = Thru::Full; |     mThruFilterMode = Thru::Full; | ||||||
|     mThruActivated  = false; |     mThruActivated  = false; | ||||||
|  | @ -120,6 +119,45 @@ void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel) | ||||||
|  @{ |  @{ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | /*! \brief Send a MIDI message.
 | ||||||
|  | \param inMessage    The message | ||||||
|  |   | ||||||
|  |  This method is used when you want to send a Message that has not been constructed | ||||||
|  |  by the library, but by an external source. | ||||||
|  |  This method does *not* check against any of the constraints. | ||||||
|  |  Typically this function is use by MIDI Bridges taking MIDI messages and passing | ||||||
|  |  them thru. | ||||||
|  |  */ | ||||||
|  | template<class Transport, class Settings, class Platform> | ||||||
|  | void MidiInterface<Transport, Settings, Platform>::send(MidiMessage inMessage) | ||||||
|  | { | ||||||
|  |     if (!inMessage.valid) | ||||||
|  |         return; | ||||||
|  |      | ||||||
|  |     if (mTransport.beginTransmission(inMessage.type)) | ||||||
|  |     { | ||||||
|  |         const StatusByte status = getStatus(inMessage.type, inMessage.channel); | ||||||
|  |         mTransport.write(status); | ||||||
|  |          | ||||||
|  |         if (inMessage.type != MidiType::SystemExclusive) | ||||||
|  |         { | ||||||
|  |             if (inMessage.length > 1) mTransport.write(inMessage.data1); | ||||||
|  |             if (inMessage.length > 2) mTransport.write(inMessage.data2); | ||||||
|  |         } else | ||||||
|  |         { | ||||||
|  |             // sysexArray does not contain the start and end tags
 | ||||||
|  |             mTransport.write(MidiType::SystemExclusiveStart); | ||||||
|  | 
 | ||||||
|  |             for (size_t i = 0; i < inMessage.getSysExSize(); i++) | ||||||
|  |                 mTransport.write(inMessage.sysexArray[i]); | ||||||
|  | 
 | ||||||
|  |             mTransport.write(MidiType::SystemExclusiveEnd); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     mTransport.endTransmission(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /*! \brief Generate and send a MIDI message from the values given.
 | /*! \brief Generate and send a MIDI message from the values given.
 | ||||||
|  \param inType    The message type (see type defines for reference) |  \param inType    The message type (see type defines for reference) | ||||||
|  \param inData1   The first data byte. |  \param inData1   The first data byte. | ||||||
|  | @ -764,12 +802,12 @@ bool MidiInterface<Transport, Settings, Platform>::parse() | ||||||
|                 mMessage.channel = 0; |                 mMessage.channel = 0; | ||||||
|                 mMessage.data1   = 0; |                 mMessage.data1   = 0; | ||||||
|                 mMessage.data2   = 0; |                 mMessage.data2   = 0; | ||||||
|  |                 mMessage.length  = 0; | ||||||
|                 mMessage.valid   = true; |                 mMessage.valid   = true; | ||||||
| 
 | 
 | ||||||
|                 // Do not reset all input attributes, Running Status must remain unchanged.
 |                 // Do not reset all input attributes, Running Status must remain unchanged.
 | ||||||
|                 // We still need to reset these
 |                 // We still need to reset these
 | ||||||
|                 mPendingMessageIndex = 0; |                 mPendingMessageIndex = 0; | ||||||
|                 mPendingMessageExpectedLenght = 0; |  | ||||||
| 
 | 
 | ||||||
|                 return true; |                 return true; | ||||||
|                 break; |                 break; | ||||||
|  | @ -779,7 +817,7 @@ bool MidiInterface<Transport, Settings, Platform>::parse() | ||||||
|             case AfterTouchChannel: |             case AfterTouchChannel: | ||||||
|             case TimeCodeQuarterFrame: |             case TimeCodeQuarterFrame: | ||||||
|             case SongSelect: |             case SongSelect: | ||||||
|                 mPendingMessageExpectedLenght = 2; |                 mMessage.length = 2; | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|                 // 3 bytes messages
 |                 // 3 bytes messages
 | ||||||
|  | @ -789,14 +827,14 @@ bool MidiInterface<Transport, Settings, Platform>::parse() | ||||||
|             case PitchBend: |             case PitchBend: | ||||||
|             case AfterTouchPoly: |             case AfterTouchPoly: | ||||||
|             case SongPosition: |             case SongPosition: | ||||||
|                 mPendingMessageExpectedLenght = 3; |                 mMessage.length = 3; | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case SystemExclusiveStart: |             case SystemExclusiveStart: | ||||||
|             case SystemExclusiveEnd: |             case SystemExclusiveEnd: | ||||||
|                 // The message can be any lenght
 |                 // The message can be any lenght
 | ||||||
|                 // between 3 and MidiMessage::sSysExMaxSize bytes
 |                 // between 3 and MidiMessage::sSysExMaxSize bytes
 | ||||||
|                 mPendingMessageExpectedLenght = MidiMessage::sSysExMaxSize; |                 mMessage.length = MidiMessage::sSysExMaxSize; | ||||||
|                 mRunningStatus_RX = InvalidType; |                 mRunningStatus_RX = InvalidType; | ||||||
|                 mMessage.sysexArray[0] = pendingType; |                 mMessage.sysexArray[0] = pendingType; | ||||||
|                 break; |                 break; | ||||||
|  | @ -809,7 +847,7 @@ bool MidiInterface<Transport, Settings, Platform>::parse() | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (mPendingMessageIndex >= (mPendingMessageExpectedLenght - 1)) |         if (mPendingMessageIndex >= (mMessage.length - 1)) | ||||||
|         { |         { | ||||||
|             // Reception complete
 |             // Reception complete
 | ||||||
|             mMessage.type    = pendingType; |             mMessage.type    = pendingType; | ||||||
|  | @ -818,7 +856,7 @@ bool MidiInterface<Transport, Settings, Platform>::parse() | ||||||
|             mMessage.data2   = 0; // Completed new message has 1 data byte
 |             mMessage.data2   = 0; // Completed new message has 1 data byte
 | ||||||
| 
 | 
 | ||||||
|             mPendingMessageIndex = 0; |             mPendingMessageIndex = 0; | ||||||
|             mPendingMessageExpectedLenght = 0; |             mMessage.length = 0; | ||||||
|             mMessage.valid = true; |             mMessage.valid = true; | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  | @ -909,7 +947,7 @@ bool MidiInterface<Transport, Settings, Platform>::parse() | ||||||
|             mPendingMessage[mPendingMessageIndex] = extracted; |             mPendingMessage[mPendingMessageIndex] = extracted; | ||||||
| 
 | 
 | ||||||
|         // Now we are going to check if we have reached the end of the message
 |         // Now we are going to check if we have reached the end of the message
 | ||||||
|         if (mPendingMessageIndex >= (mPendingMessageExpectedLenght - 1)) |         if (mPendingMessageIndex >= (mMessage.length - 1)) | ||||||
|         { |         { | ||||||
|             // "FML" case: fall down here with an overflown SysEx..
 |             // "FML" case: fall down here with an overflown SysEx..
 | ||||||
|             // This means we received the last possible data byte that can fit
 |             // This means we received the last possible data byte that can fit
 | ||||||
|  | @ -930,11 +968,11 @@ bool MidiInterface<Transport, Settings, Platform>::parse() | ||||||
|             mMessage.data1 = mPendingMessage[1]; |             mMessage.data1 = mPendingMessage[1]; | ||||||
| 
 | 
 | ||||||
|             // Save data2 only if applicable
 |             // Save data2 only if applicable
 | ||||||
|             mMessage.data2 = mPendingMessageExpectedLenght == 3 ? mPendingMessage[2] : 0; |             mMessage.data2 = mMessage.length == 3 ? mPendingMessage[2] : 0; | ||||||
| 
 | 
 | ||||||
|             // Reset local variables
 |             // Reset local variables
 | ||||||
|             mPendingMessageIndex = 0; |             mPendingMessageIndex = 0; | ||||||
|             mPendingMessageExpectedLenght = 0; |             mMessage.length = 0; | ||||||
| 
 | 
 | ||||||
|             mMessage.valid = true; |             mMessage.valid = true; | ||||||
| 
 | 
 | ||||||
|  | @ -1014,7 +1052,7 @@ template<class Transport, class Settings, class Platform> | ||||||
| inline void MidiInterface<Transport, Settings, Platform>::resetInput() | inline void MidiInterface<Transport, Settings, Platform>::resetInput() | ||||||
| { | { | ||||||
|     mPendingMessageIndex = 0; |     mPendingMessageIndex = 0; | ||||||
|     mPendingMessageExpectedLenght = 0; |     mMessage.length = 0; | ||||||
|     mRunningStatus_RX = InvalidType; |     mRunningStatus_RX = InvalidType; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -91,6 +91,10 @@ struct Message | ||||||
|      */ |      */ | ||||||
|     bool valid; |     bool valid; | ||||||
| 
 | 
 | ||||||
|  |     /*! Total Length of the message.
 | ||||||
|  |      */ | ||||||
|  |     unsigned length; | ||||||
|  |      | ||||||
|     inline unsigned getSysExSize() const |     inline unsigned getSysExSize() const | ||||||
|     { |     { | ||||||
|         const unsigned size = unsigned(data2) << 8 | data1; |         const unsigned size = unsigned(data2) << 8 | data1; | ||||||
|  |  | ||||||
|  | @ -53,9 +53,9 @@ private: | ||||||
|  */ |  */ | ||||||
| #define MIDI_CREATE_INSTANCE(Type, SerialPort, Name)  \ | #define MIDI_CREATE_INSTANCE(Type, SerialPort, Name)  \ | ||||||
|     typedef MIDI_NAMESPACE::serialMIDI<Type> __smt;\ |     typedef MIDI_NAMESPACE::serialMIDI<Type> __smt;\ | ||||||
|     typedef MIDI_NAMESPACE::MidiInterface<__smt> __mismt;\ |     typedef MIDI_NAMESPACE::MidiInterface<__smt> TypedMidiInterface;\ | ||||||
|     __smt serialMidi(SerialPort);\ |     __smt serialMidi(SerialPort);\ | ||||||
|     __mismt Name((__smt&)serialMidi); |     TypedMidiInterface Name((__smt&)serialMidi); | ||||||
| 
 | 
 | ||||||
| #if defined(ARDUINO_SAM_DUE) || defined(USBCON) || defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MKL26Z64__) | #if defined(ARDUINO_SAM_DUE) || defined(USBCON) || defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MKL26Z64__) | ||||||
|     // Leonardo, Due and other USB boards use Serial1 by default.
 |     // Leonardo, Due and other USB boards use Serial1 by default.
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 lathoub
						lathoub