Merge pull request #247 from FortySevenEffects/chaining

chaining for all commands, callbacks and setters
This commit is contained in:
lathoub 2021-10-10 16:47:07 +02:00 committed by GitHub
commit 50e33c8b4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 204 additions and 120 deletions

View File

@ -17,6 +17,7 @@ jobs:
- Basic_IO - Basic_IO
- Bench - Bench
- Callbacks - Callbacks
- Chaining
- DualMerger - DualMerger
- ErrorCallback - ErrorCallback
- Input - Input

View File

@ -0,0 +1,37 @@
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
void setup()
{
pinMode(2, INPUT);
MIDI // chaining MIDI commands - order is from top to bottom (turnThruOff,... begin)
.turnThruOff()
// using a lamdba function for this callbacks
.setHandleNoteOn([](byte channel, byte note, byte velocity)
{
// Do whatever you want when a note is pressed.
// Try to keep your callbacks short (no delays ect)
// otherwise it would slow down the loop() and have a bad impact
// on real-time performance.
})
.setHandleNoteOff([](byte channel, byte note, byte velocity)
{
// Do something when the note is released.
// Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
})
.begin(MIDI_CHANNEL_OMNI); // Initiate MIDI communications, listen to all channels
}
void loop()
{
// Call MIDI.read the fastest you can for real-time performance.
MIDI.read();
if (digitalRead(2))
MIDI // chained sendNoteOn commands
.sendNoteOn(42, 127, 1)
.sendNoteOn(40, 54, 1);
}

View File

@ -62,94 +62,94 @@ public:
inline ~MidiInterface(); inline ~MidiInterface();
public: public:
void begin(Channel inChannel = 1); MidiInterface& begin(Channel inChannel = 1);
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// MIDI Output // MIDI Output
public: public:
inline void sendNoteOn(DataByte inNoteNumber, inline MidiInterface& sendNoteOn(DataByte inNoteNumber,
DataByte inVelocity, DataByte inVelocity,
Channel inChannel); Channel inChannel);
inline void sendNoteOff(DataByte inNoteNumber, inline MidiInterface& sendNoteOff(DataByte inNoteNumber,
DataByte inVelocity, DataByte inVelocity,
Channel inChannel); Channel inChannel);
inline void sendProgramChange(DataByte inProgramNumber, inline MidiInterface& sendProgramChange(DataByte inProgramNumber,
Channel inChannel); Channel inChannel);
inline void sendControlChange(DataByte inControlNumber, inline MidiInterface& sendControlChange(DataByte inControlNumber,
DataByte inControlValue, DataByte inControlValue,
Channel inChannel); Channel inChannel);
inline void sendPitchBend(int inPitchValue, Channel inChannel); inline MidiInterface& sendPitchBend(int inPitchValue, Channel inChannel);
inline void sendPitchBend(double inPitchValue, Channel inChannel); inline MidiInterface& sendPitchBend(double inPitchValue, Channel inChannel);
inline void sendPolyPressure(DataByte inNoteNumber, inline MidiInterface& sendPolyPressure(DataByte inNoteNumber,
DataByte inPressure, DataByte inPressure,
Channel inChannel) __attribute__ ((deprecated)); Channel inChannel) __attribute__ ((deprecated));
inline void sendAfterTouch(DataByte inPressure, inline MidiInterface& sendAfterTouch(DataByte inPressure,
Channel inChannel); Channel inChannel);
inline void sendAfterTouch(DataByte inNoteNumber, inline MidiInterface& sendAfterTouch(DataByte inNoteNumber,
DataByte inPressure, DataByte inPressure,
Channel inChannel); Channel inChannel);
inline void sendSysEx(unsigned inLength, inline MidiInterface& sendSysEx(unsigned inLength,
const byte* inArray, const byte* inArray,
bool inArrayContainsBoundaries = false); bool inArrayContainsBoundaries = false);
inline void sendTimeCodeQuarterFrame(DataByte inTypeNibble, inline MidiInterface& sendTimeCodeQuarterFrame(DataByte inTypeNibble,
DataByte inValuesNibble); DataByte inValuesNibble);
inline void sendTimeCodeQuarterFrame(DataByte inData); inline MidiInterface& sendTimeCodeQuarterFrame(DataByte inData);
inline void sendSongPosition(unsigned inBeats); inline MidiInterface& sendSongPosition(unsigned inBeats);
inline void sendSongSelect(DataByte inSongNumber); inline MidiInterface& sendSongSelect(DataByte inSongNumber);
inline void sendTuneRequest(); inline MidiInterface& sendTuneRequest();
inline void sendCommon(MidiType inType, unsigned = 0); inline MidiInterface& sendCommon(MidiType inType, unsigned = 0);
inline void sendClock() { sendRealTime(Clock); }; inline MidiInterface& sendClock() { sendRealTime(Clock); };
inline void sendStart() { sendRealTime(Start); }; inline MidiInterface& sendStart() { sendRealTime(Start); };
inline void sendStop() { sendRealTime(Stop); }; inline MidiInterface& sendStop() { sendRealTime(Stop); };
inline void sendTick() { sendRealTime(Tick); }; inline MidiInterface& sendTick() { sendRealTime(Tick); };
inline void sendContinue() { sendRealTime(Continue); }; inline MidiInterface& sendContinue() { sendRealTime(Continue); };
inline void sendActiveSensing() { sendRealTime(ActiveSensing); }; inline MidiInterface& sendActiveSensing() { sendRealTime(ActiveSensing); };
inline void sendSystemReset() { sendRealTime(SystemReset); }; inline MidiInterface& sendSystemReset() { sendRealTime(SystemReset); };
inline void sendRealTime(MidiType inType); inline MidiInterface& sendRealTime(MidiType inType);
inline void beginRpn(unsigned inNumber, inline MidiInterface& beginRpn(unsigned inNumber,
Channel inChannel); Channel inChannel);
inline void sendRpnValue(unsigned inValue, inline MidiInterface& sendRpnValue(unsigned inValue,
Channel inChannel); Channel inChannel);
inline void sendRpnValue(byte inMsb, inline MidiInterface& sendRpnValue(byte inMsb,
byte inLsb, byte inLsb,
Channel inChannel); Channel inChannel);
inline void sendRpnIncrement(byte inAmount, inline MidiInterface& sendRpnIncrement(byte inAmount,
Channel inChannel); Channel inChannel);
inline void sendRpnDecrement(byte inAmount, inline MidiInterface& sendRpnDecrement(byte inAmount,
Channel inChannel); Channel inChannel);
inline void endRpn(Channel inChannel); inline MidiInterface& endRpn(Channel inChannel);
inline void beginNrpn(unsigned inNumber, inline MidiInterface& beginNrpn(unsigned inNumber,
Channel inChannel); Channel inChannel);
inline void sendNrpnValue(unsigned inValue, inline MidiInterface& sendNrpnValue(unsigned inValue,
Channel inChannel); Channel inChannel);
inline void sendNrpnValue(byte inMsb, inline MidiInterface& sendNrpnValue(byte inMsb,
byte inLsb, byte inLsb,
Channel inChannel); Channel inChannel);
inline void sendNrpnIncrement(byte inAmount, inline MidiInterface& sendNrpnIncrement(byte inAmount,
Channel inChannel); Channel inChannel);
inline void sendNrpnDecrement(byte inAmount, inline MidiInterface& sendNrpnDecrement(byte inAmount,
Channel inChannel); Channel inChannel);
inline void endNrpn(Channel inChannel); inline MidiInterface& endNrpn(Channel inChannel);
inline void send(const MidiMessage&); inline MidiInterface& send(const MidiMessage&);
public: public:
void send(MidiType inType, MidiInterface& send(MidiType inType,
DataByte inData1, DataByte inData1,
DataByte inData2, DataByte inData2,
Channel inChannel); Channel inChannel);
@ -172,7 +172,7 @@ public:
public: public:
inline Channel getInputChannel() const; inline Channel getInputChannel() const;
inline void setInputChannel(Channel inChannel); inline MidiInterface& setInputChannel(Channel inChannel);
public: public:
static inline MidiType getTypeFromStatusByte(byte inStatus); static inline MidiType getTypeFromStatusByte(byte inStatus);
@ -183,29 +183,29 @@ public:
// Input Callbacks // Input Callbacks
public: public:
inline void setHandleMessage(void (*fptr)(const MidiMessage&)) { mMessageCallback = fptr; }; inline MidiInterface& setHandleMessage(void (*fptr)(const MidiMessage&)) { mMessageCallback = fptr; return *this; };
inline void setHandleError(ErrorCallback fptr) { mErrorCallback = fptr; } inline MidiInterface& setHandleError(ErrorCallback fptr) { mErrorCallback = fptr; return *this; };
inline void setHandleNoteOff(NoteOffCallback fptr) { mNoteOffCallback = fptr; } inline MidiInterface& setHandleNoteOff(NoteOffCallback fptr) { mNoteOffCallback = fptr; return *this; };
inline void setHandleNoteOn(NoteOnCallback fptr) { mNoteOnCallback = fptr; } inline MidiInterface& setHandleNoteOn(NoteOnCallback fptr) { mNoteOnCallback = fptr; return *this; };
inline void setHandleAfterTouchPoly(AfterTouchPolyCallback fptr) { mAfterTouchPolyCallback = fptr; } inline MidiInterface& setHandleAfterTouchPoly(AfterTouchPolyCallback fptr) { mAfterTouchPolyCallback = fptr; return *this; };
inline void setHandleControlChange(ControlChangeCallback fptr) { mControlChangeCallback = fptr; } inline MidiInterface& setHandleControlChange(ControlChangeCallback fptr) { mControlChangeCallback = fptr; return *this; };
inline void setHandleProgramChange(ProgramChangeCallback fptr) { mProgramChangeCallback = fptr; } inline MidiInterface& setHandleProgramChange(ProgramChangeCallback fptr) { mProgramChangeCallback = fptr; return *this; };
inline void setHandleAfterTouchChannel(AfterTouchChannelCallback fptr) { mAfterTouchChannelCallback = fptr; } inline MidiInterface& setHandleAfterTouchChannel(AfterTouchChannelCallback fptr) { mAfterTouchChannelCallback = fptr; return *this; };
inline void setHandlePitchBend(PitchBendCallback fptr) { mPitchBendCallback = fptr; } inline MidiInterface& setHandlePitchBend(PitchBendCallback fptr) { mPitchBendCallback = fptr; return *this; };
inline void setHandleSystemExclusive(SystemExclusiveCallback fptr) { mSystemExclusiveCallback = fptr; } inline MidiInterface& setHandleSystemExclusive(SystemExclusiveCallback fptr) { mSystemExclusiveCallback = fptr; return *this; };
inline void setHandleTimeCodeQuarterFrame(TimeCodeQuarterFrameCallback fptr) { mTimeCodeQuarterFrameCallback = fptr; } inline MidiInterface& setHandleTimeCodeQuarterFrame(TimeCodeQuarterFrameCallback fptr) { mTimeCodeQuarterFrameCallback = fptr; return *this; };
inline void setHandleSongPosition(SongPositionCallback fptr) { mSongPositionCallback = fptr; } inline MidiInterface& setHandleSongPosition(SongPositionCallback fptr) { mSongPositionCallback = fptr; return *this; };
inline void setHandleSongSelect(SongSelectCallback fptr) { mSongSelectCallback = fptr; } inline MidiInterface& setHandleSongSelect(SongSelectCallback fptr) { mSongSelectCallback = fptr; return *this; };
inline void setHandleTuneRequest(TuneRequestCallback fptr) { mTuneRequestCallback = fptr; } inline MidiInterface& setHandleTuneRequest(TuneRequestCallback fptr) { mTuneRequestCallback = fptr; return *this; };
inline void setHandleClock(ClockCallback fptr) { mClockCallback = fptr; } inline MidiInterface& setHandleClock(ClockCallback fptr) { mClockCallback = fptr; return *this; };
inline void setHandleStart(StartCallback fptr) { mStartCallback = fptr; } inline MidiInterface& setHandleStart(StartCallback fptr) { mStartCallback = fptr; return *this; };
inline void setHandleTick(TickCallback fptr) { mTickCallback = fptr; } inline MidiInterface& setHandleTick(TickCallback fptr) { mTickCallback = fptr; return *this; };
inline void setHandleContinue(ContinueCallback fptr) { mContinueCallback = fptr; } inline MidiInterface& setHandleContinue(ContinueCallback fptr) { mContinueCallback = fptr; return *this; };
inline void setHandleStop(StopCallback fptr) { mStopCallback = fptr; } inline MidiInterface& setHandleStop(StopCallback fptr) { mStopCallback = fptr; return *this; };
inline void setHandleActiveSensing(ActiveSensingCallback fptr) { mActiveSensingCallback = fptr; } inline MidiInterface& setHandleActiveSensing(ActiveSensingCallback fptr) { mActiveSensingCallback = fptr; return *this; };
inline void setHandleSystemReset(SystemResetCallback fptr) { mSystemResetCallback = fptr; } inline MidiInterface& setHandleSystemReset(SystemResetCallback fptr) { mSystemResetCallback = fptr; return *this; };
inline void disconnectCallbackFromType(MidiType inType); inline MidiInterface& disconnectCallbackFromType(MidiType inType);
private: private:
void launchCallback(); void launchCallback();
@ -239,9 +239,9 @@ public:
inline Thru::Mode getFilterMode() const; inline Thru::Mode getFilterMode() const;
inline bool getThruState() const; inline bool getThruState() const;
inline void turnThruOn(Thru::Mode inThruFilterMode = Thru::Full); inline MidiInterface& turnThruOn(Thru::Mode inThruFilterMode = Thru::Full);
inline void turnThruOff(); inline MidiInterface& turnThruOff();
inline void setThruFilterMode(Thru::Mode inThruFilterMode); inline MidiInterface& setThruFilterMode(Thru::Mode inThruFilterMode);
private: private:
void thruFilter(byte inChannel); void thruFilter(byte inChannel);

View File

@ -69,7 +69,7 @@ inline MidiInterface<Transport, Settings, Platform>::~MidiInterface()
- Full thru mirroring - Full thru mirroring
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel) MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel)
{ {
// Initialise the Transport layer // Initialise the Transport layer
mTransport.begin(); mTransport.begin();
@ -95,6 +95,8 @@ void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel)
mThruFilterMode = Thru::Full; mThruFilterMode = Thru::Full;
mThruActivated = mTransport.thruActivated; mThruActivated = mTransport.thruActivated;
return *this;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -115,10 +117,10 @@ void MidiInterface<Transport, Settings, Platform>::begin(Channel inChannel)
them thru. them thru.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::send(const MidiMessage& inMessage) MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::send(const MidiMessage& inMessage)
{ {
if (!inMessage.valid) if (!inMessage.valid)
return; return *this;
if (mTransport.beginTransmission(inMessage.type)) if (mTransport.beginTransmission(inMessage.type))
{ {
@ -142,6 +144,8 @@ void MidiInterface<Transport, Settings, Platform>::send(const MidiMessage& inMes
} }
mTransport.endTransmission(); mTransport.endTransmission();
updateLastSentTime(); updateLastSentTime();
return *this;
} }
@ -157,7 +161,7 @@ void MidiInterface<Transport, Settings, Platform>::send(const MidiMessage& inMes
from your code, at your own risks. from your code, at your own risks.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::send(MidiType inType, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
DataByte inData1, DataByte inData1,
DataByte inData2, DataByte inData2,
Channel inChannel) Channel inChannel)
@ -169,7 +173,7 @@ void MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
inChannel == MIDI_CHANNEL_OMNI || inChannel == MIDI_CHANNEL_OMNI ||
inType < 0x80) inType < 0x80)
{ {
return; // Don't send anything return *this; // Don't send anything
} }
// Protection: remove MSBs on data // Protection: remove MSBs on data
inData1 &= 0x7f; inData1 &= 0x7f;
@ -209,6 +213,8 @@ void MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
{ {
sendRealTime(inType); // System Real-time and 1 byte. sendRealTime(inType); // System Real-time and 1 byte.
} }
return *this;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -223,11 +229,11 @@ void MidiInterface<Transport, Settings, Platform>::send(MidiType inType,
http://www.phys.unsw.edu.au/jw/notes.html http://www.phys.unsw.edu.au/jw/notes.html
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendNoteOn(DataByte inNoteNumber, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNoteOn(DataByte inNoteNumber,
DataByte inVelocity, DataByte inVelocity,
Channel inChannel) Channel inChannel)
{ {
send(NoteOn, inNoteNumber, inVelocity, inChannel); return send(NoteOn, inNoteNumber, inVelocity, inChannel);
} }
/*! \brief Send a Note Off message /*! \brief Send a Note Off message
@ -242,11 +248,11 @@ void MidiInterface<Transport, Settings, Platform>::sendNoteOn(DataByte inNoteNum
http://www.phys.unsw.edu.au/jw/notes.html http://www.phys.unsw.edu.au/jw/notes.html
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendNoteOff(DataByte inNoteNumber, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNoteOff(DataByte inNoteNumber,
DataByte inVelocity, DataByte inVelocity,
Channel inChannel) Channel inChannel)
{ {
send(NoteOff, inNoteNumber, inVelocity, inChannel); return send(NoteOff, inNoteNumber, inVelocity, inChannel);
} }
/*! \brief Send a Program Change message /*! \brief Send a Program Change message
@ -254,10 +260,10 @@ void MidiInterface<Transport, Settings, Platform>::sendNoteOff(DataByte inNoteNu
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendProgramChange(DataByte inProgramNumber, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendProgramChange(DataByte inProgramNumber,
Channel inChannel) Channel inChannel)
{ {
send(ProgramChange, inProgramNumber, 0, inChannel); return send(ProgramChange, inProgramNumber, 0, inChannel);
} }
/*! \brief Send a Control Change message /*! \brief Send a Control Change message
@ -267,11 +273,11 @@ void MidiInterface<Transport, Settings, Platform>::sendProgramChange(DataByte in
@see MidiControlChangeNumber @see MidiControlChangeNumber
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendControlChange(DataByte inControlNumber, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendControlChange(DataByte inControlNumber,
DataByte inControlValue, DataByte inControlValue,
Channel inChannel) Channel inChannel)
{ {
send(ControlChange, inControlNumber, inControlValue, inChannel); return send(ControlChange, inControlNumber, inControlValue, inChannel);
} }
/*! \brief Send a Polyphonic AfterTouch message (applies to a specified note) /*! \brief Send a Polyphonic AfterTouch message (applies to a specified note)
@ -282,11 +288,11 @@ void MidiInterface<Transport, Settings, Platform>::sendControlChange(DataByte in
library, @see sendAfterTouch to send polyphonic and monophonic AfterTouch messages. library, @see sendAfterTouch to send polyphonic and monophonic AfterTouch messages.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendPolyPressure(DataByte inNoteNumber, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendPolyPressure(DataByte inNoteNumber,
DataByte inPressure, DataByte inPressure,
Channel inChannel) Channel inChannel)
{ {
send(AfterTouchPoly, inNoteNumber, inPressure, inChannel); return send(AfterTouchPoly, inNoteNumber, inPressure, inChannel);
} }
/*! \brief Send a MonoPhonic AfterTouch message (applies to all notes) /*! \brief Send a MonoPhonic AfterTouch message (applies to all notes)
@ -294,10 +300,10 @@ void MidiInterface<Transport, Settings, Platform>::sendPolyPressure(DataByte inN
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inPressure, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inPressure,
Channel inChannel) Channel inChannel)
{ {
send(AfterTouchChannel, inPressure, 0, inChannel); return send(AfterTouchChannel, inPressure, 0, inChannel);
} }
/*! \brief Send a Polyphonic AfterTouch message (applies to a specified note) /*! \brief Send a Polyphonic AfterTouch message (applies to a specified note)
@ -307,11 +313,11 @@ void MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inPre
@see Replaces sendPolyPressure (which is now deprecated). @see Replaces sendPolyPressure (which is now deprecated).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inNoteNumber, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inNoteNumber,
DataByte inPressure, DataByte inPressure,
Channel inChannel) Channel inChannel)
{ {
send(AfterTouchPoly, inNoteNumber, inPressure, inChannel); return send(AfterTouchPoly, inNoteNumber, inPressure, inChannel);
} }
/*! \brief Send a Pitch Bend message using a signed integer value. /*! \brief Send a Pitch Bend message using a signed integer value.
@ -321,11 +327,11 @@ void MidiInterface<Transport, Settings, Platform>::sendAfterTouch(DataByte inNot
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendPitchBend(int inPitchValue, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendPitchBend(int inPitchValue,
Channel inChannel) Channel inChannel)
{ {
const unsigned bend = unsigned(inPitchValue - int(MIDI_PITCHBEND_MIN)); const unsigned bend = unsigned(inPitchValue - int(MIDI_PITCHBEND_MIN));
send(PitchBend, (bend & 0x7f), (bend >> 7) & 0x7f, inChannel); return send(PitchBend, (bend & 0x7f), (bend >> 7) & 0x7f, inChannel);
} }
@ -336,12 +342,12 @@ void MidiInterface<Transport, Settings, Platform>::sendPitchBend(int inPitchValu
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendPitchBend(double inPitchValue, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendPitchBend(double inPitchValue,
Channel inChannel) Channel inChannel)
{ {
const int scale = inPitchValue > 0.0 ? MIDI_PITCHBEND_MAX : - MIDI_PITCHBEND_MIN; const int scale = inPitchValue > 0.0 ? MIDI_PITCHBEND_MAX : - MIDI_PITCHBEND_MIN;
const int value = int(inPitchValue * double(scale)); const int value = int(inPitchValue * double(scale));
sendPitchBend(value, inChannel); return sendPitchBend(value, inChannel);
} }
/*! \brief Generate and send a System Exclusive frame. /*! \brief Generate and send a System Exclusive frame.
@ -354,7 +360,7 @@ void MidiInterface<Transport, Settings, Platform>::sendPitchBend(double inPitchV
with previous versions of the library. with previous versions of the library.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendSysEx(unsigned inLength, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendSysEx(unsigned inLength,
const byte* inArray, const byte* inArray,
bool inArrayContainsBoundaries) bool inArrayContainsBoundaries)
{ {
@ -377,6 +383,8 @@ void MidiInterface<Transport, Settings, Platform>::sendSysEx(unsigned inLength,
if (Settings::UseRunningStatus) if (Settings::UseRunningStatus)
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
return *this;
} }
/*! \brief Send a Tune Request message. /*! \brief Send a Tune Request message.
@ -385,9 +393,9 @@ void MidiInterface<Transport, Settings, Platform>::sendSysEx(unsigned inLength,
it should tune its oscillators (if equipped with any). it should tune its oscillators (if equipped with any).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendTuneRequest() MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendTuneRequest()
{ {
sendCommon(TuneRequest); return sendCommon(TuneRequest);
} }
/*! \brief Send a MIDI Time Code Quarter Frame. /*! \brief Send a MIDI Time Code Quarter Frame.
@ -397,11 +405,11 @@ void MidiInterface<Transport, Settings, Platform>::sendTuneRequest()
See MIDI Specification for more information. See MIDI Specification for more information.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(DataByte inTypeNibble, MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
DataByte inValuesNibble) DataByte inValuesNibble)
{ {
const byte data = byte((((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f))); const byte data = byte((((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f)));
sendTimeCodeQuarterFrame(data); return sendTimeCodeQuarterFrame(data);
} }
/*! \brief Send a MIDI Time Code Quarter Frame. /*! \brief Send a MIDI Time Code Quarter Frame.
@ -411,25 +419,25 @@ void MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(Data
you can send the byte here. you can send the byte here.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(DataByte inData) MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendTimeCodeQuarterFrame(DataByte inData)
{ {
sendCommon(TimeCodeQuarterFrame, inData); return sendCommon(TimeCodeQuarterFrame, inData);
} }
/*! \brief Send a Song Position Pointer message. /*! \brief Send a Song Position Pointer message.
\param inBeats The number of beats since the start of the song. \param inBeats The number of beats since the start of the song.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendSongPosition(unsigned inBeats) MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendSongPosition(unsigned inBeats)
{ {
sendCommon(SongPosition, inBeats); return sendCommon(SongPosition, inBeats);
} }
/*! \brief Send a Song Select message */ /*! \brief Send a Song Select message */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendSongSelect(DataByte inSongNumber) MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendSongSelect(DataByte inSongNumber)
{ {
sendCommon(SongSelect, inSongNumber); return sendCommon(SongSelect, inSongNumber);
} }
/*! \brief Send a Common message. Common messages reset the running status. /*! \brief Send a Common message. Common messages reset the running status.
@ -440,7 +448,7 @@ void MidiInterface<Transport, Settings, Platform>::sendSongSelect(DataByte inSon
\param inData1 The byte that goes with the common message. \param inData1 The byte that goes with the common message.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, unsigned inData1) MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, unsigned inData1)
{ {
switch (inType) switch (inType)
{ {
@ -451,7 +459,7 @@ void MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, u
break; break;
default: default:
// Invalid Common marker // Invalid Common marker
return; return *this;
} }
if (mTransport.beginTransmission(inType)) if (mTransport.beginTransmission(inType))
@ -482,6 +490,8 @@ void MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, u
if (Settings::UseRunningStatus) if (Settings::UseRunningStatus)
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
return *this;
} }
/*! \brief Send a Real Time (one byte) message. /*! \brief Send a Real Time (one byte) message.
@ -491,7 +501,7 @@ void MidiInterface<Transport, Settings, Platform>::sendCommon(MidiType inType, u
@see MidiType @see MidiType
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::sendRealTime(MidiType inType) MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRealTime(MidiType inType)
{ {
// Do not invalidate Running Status for real-time messages // Do not invalidate Running Status for real-time messages
// as they can be interleaved within any message. // as they can be interleaved within any message.
@ -515,6 +525,8 @@ void MidiInterface<Transport, Settings, Platform>::sendRealTime(MidiType inType)
// Invalid Real Time marker // Invalid Real Time marker
break; break;
} }
return *this;
} }
/*! \brief Start a Registered Parameter Number frame. /*! \brief Start a Registered Parameter Number frame.
@ -522,7 +534,7 @@ void MidiInterface<Transport, Settings, Platform>::sendRealTime(MidiType inType)
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::beginRpn(unsigned inNumber, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::beginRpn(unsigned inNumber,
Channel inChannel) Channel inChannel)
{ {
if (mCurrentRpnNumber != inNumber) if (mCurrentRpnNumber != inNumber)
@ -533,6 +545,8 @@ inline void MidiInterface<Transport, Settings, Platform>::beginRpn(unsigned inNu
sendControlChange(RPNMSB, numMsb, inChannel); sendControlChange(RPNMSB, numMsb, inChannel);
mCurrentRpnNumber = inNumber; mCurrentRpnNumber = inNumber;
} }
return *this;
} }
/*! \brief Send a 14-bit value for the currently selected RPN number. /*! \brief Send a 14-bit value for the currently selected RPN number.
@ -540,13 +554,15 @@ inline void MidiInterface<Transport, Settings, Platform>::beginRpn(unsigned inNu
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::sendRpnValue(unsigned inValue, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRpnValue(unsigned inValue,
Channel inChannel) Channel inChannel)
{; {;
const byte valMsb = 0x7f & (inValue >> 7); const byte valMsb = 0x7f & (inValue >> 7);
const byte valLsb = 0x7f & inValue; const byte valLsb = 0x7f & inValue;
sendControlChange(DataEntryMSB, valMsb, inChannel); sendControlChange(DataEntryMSB, valMsb, inChannel);
sendControlChange(DataEntryLSB, valLsb, inChannel); sendControlChange(DataEntryLSB, valLsb, inChannel);
return *this;
} }
/*! \brief Send separate MSB/LSB values for the currently selected RPN number. /*! \brief Send separate MSB/LSB values for the currently selected RPN number.
@ -555,32 +571,38 @@ inline void MidiInterface<Transport, Settings, Platform>::sendRpnValue(unsigned
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::sendRpnValue(byte inMsb, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRpnValue(byte inMsb,
byte inLsb, byte inLsb,
Channel inChannel) Channel inChannel)
{ {
sendControlChange(DataEntryMSB, inMsb, inChannel); sendControlChange(DataEntryMSB, inMsb, inChannel);
sendControlChange(DataEntryLSB, inLsb, inChannel); sendControlChange(DataEntryLSB, inLsb, inChannel);
return *this;
} }
/* \brief Increment the value of the currently selected RPN number by the specified amount. /* \brief Increment the value of the currently selected RPN number by the specified amount.
\param inAmount The amount to add to the currently selected RPN value. \param inAmount The amount to add to the currently selected RPN value.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::sendRpnIncrement(byte inAmount, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRpnIncrement(byte inAmount,
Channel inChannel) Channel inChannel)
{ {
sendControlChange(DataIncrement, inAmount, inChannel); sendControlChange(DataIncrement, inAmount, inChannel);
return *this;
} }
/* \brief Decrement the value of the currently selected RPN number by the specified amount. /* \brief Decrement the value of the currently selected RPN number by the specified amount.
\param inAmount The amount to subtract to the currently selected RPN value. \param inAmount The amount to subtract to the currently selected RPN value.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::sendRpnDecrement(byte inAmount, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendRpnDecrement(byte inAmount,
Channel inChannel) Channel inChannel)
{ {
sendControlChange(DataDecrement, inAmount, inChannel); sendControlChange(DataDecrement, inAmount, inChannel);
return *this;
} }
/*! \brief Terminate an RPN frame. /*! \brief Terminate an RPN frame.
@ -588,11 +610,13 @@ This will send a Null Function to deselect the currently selected RPN.
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::endRpn(Channel inChannel) inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::endRpn(Channel inChannel)
{ {
sendControlChange(RPNLSB, 0x7f, inChannel); sendControlChange(RPNLSB, 0x7f, inChannel);
sendControlChange(RPNMSB, 0x7f, inChannel); sendControlChange(RPNMSB, 0x7f, inChannel);
mCurrentRpnNumber = 0xffff; mCurrentRpnNumber = 0xffff;
return *this;
} }
@ -602,7 +626,7 @@ inline void MidiInterface<Transport, Settings, Platform>::endRpn(Channel inChann
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::beginNrpn(unsigned inNumber, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::beginNrpn(unsigned inNumber,
Channel inChannel) Channel inChannel)
{ {
if (mCurrentNrpnNumber != inNumber) if (mCurrentNrpnNumber != inNumber)
@ -613,6 +637,8 @@ inline void MidiInterface<Transport, Settings, Platform>::beginNrpn(unsigned inN
sendControlChange(NRPNMSB, numMsb, inChannel); sendControlChange(NRPNMSB, numMsb, inChannel);
mCurrentNrpnNumber = inNumber; mCurrentNrpnNumber = inNumber;
} }
return *this;
} }
/*! \brief Send a 14-bit value for the currently selected NRPN number. /*! \brief Send a 14-bit value for the currently selected NRPN number.
@ -620,13 +646,15 @@ inline void MidiInterface<Transport, Settings, Platform>::beginNrpn(unsigned inN
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::sendNrpnValue(unsigned inValue, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNrpnValue(unsigned inValue,
Channel inChannel) Channel inChannel)
{; {
const byte valMsb = 0x7f & (inValue >> 7); const byte valMsb = 0x7f & (inValue >> 7);
const byte valLsb = 0x7f & inValue; const byte valLsb = 0x7f & inValue;
sendControlChange(DataEntryMSB, valMsb, inChannel); sendControlChange(DataEntryMSB, valMsb, inChannel);
sendControlChange(DataEntryLSB, valLsb, inChannel); sendControlChange(DataEntryLSB, valLsb, inChannel);
return *this;
} }
/*! \brief Send separate MSB/LSB values for the currently selected NRPN number. /*! \brief Send separate MSB/LSB values for the currently selected NRPN number.
@ -635,32 +663,38 @@ inline void MidiInterface<Transport, Settings, Platform>::sendNrpnValue(unsigned
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::sendNrpnValue(byte inMsb, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNrpnValue(byte inMsb,
byte inLsb, byte inLsb,
Channel inChannel) Channel inChannel)
{ {
sendControlChange(DataEntryMSB, inMsb, inChannel); sendControlChange(DataEntryMSB, inMsb, inChannel);
sendControlChange(DataEntryLSB, inLsb, inChannel); sendControlChange(DataEntryLSB, inLsb, inChannel);
return *this;
} }
/* \brief Increment the value of the currently selected NRPN number by the specified amount. /* \brief Increment the value of the currently selected NRPN number by the specified amount.
\param inAmount The amount to add to the currently selected NRPN value. \param inAmount The amount to add to the currently selected NRPN value.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::sendNrpnIncrement(byte inAmount, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNrpnIncrement(byte inAmount,
Channel inChannel) Channel inChannel)
{ {
sendControlChange(DataIncrement, inAmount, inChannel); sendControlChange(DataIncrement, inAmount, inChannel);
return *this;
} }
/* \brief Decrement the value of the currently selected NRPN number by the specified amount. /* \brief Decrement the value of the currently selected NRPN number by the specified amount.
\param inAmount The amount to subtract to the currently selected NRPN value. \param inAmount The amount to subtract to the currently selected NRPN value.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::sendNrpnDecrement(byte inAmount, inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::sendNrpnDecrement(byte inAmount,
Channel inChannel) Channel inChannel)
{ {
sendControlChange(DataDecrement, inAmount, inChannel); sendControlChange(DataDecrement, inAmount, inChannel);
return *this;
} }
/*! \brief Terminate an NRPN frame. /*! \brief Terminate an NRPN frame.
@ -668,11 +702,13 @@ This will send a Null Function to deselect the currently selected NRPN.
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::endNrpn(Channel inChannel) inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::endNrpn(Channel inChannel)
{ {
sendControlChange(NRPNLSB, 0x7f, inChannel); sendControlChange(NRPNLSB, 0x7f, inChannel);
sendControlChange(NRPNMSB, 0x7f, inChannel); sendControlChange(NRPNMSB, 0x7f, inChannel);
mCurrentNrpnNumber = 0xffff; mCurrentNrpnNumber = 0xffff;
return *this;
} }
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
@ -1212,9 +1248,11 @@ inline Channel MidiInterface<Transport, Settings, Platform>::getInputChannel() c
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input. if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::setInputChannel(Channel inChannel) inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::setInputChannel(Channel inChannel)
{ {
mInputChannel = inChannel; mInputChannel = inChannel;
return *this;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -1269,7 +1307,7 @@ bool MidiInterface<Transport, Settings, Platform>::isChannelMessage(MidiType inT
When a message of this type is received, no function will be called. When a message of this type is received, no function will be called.
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
void MidiInterface<Transport, Settings, Platform>::disconnectCallbackFromType(MidiType inType) MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::disconnectCallbackFromType(MidiType inType)
{ {
switch (inType) switch (inType)
{ {
@ -1295,6 +1333,8 @@ void MidiInterface<Transport, Settings, Platform>::disconnectCallbackFromType(Mi
default: default:
break; break;
} }
return *this;
} }
/*! @} */ // End of doc group MIDI Callbacks /*! @} */ // End of doc group MIDI Callbacks
@ -1361,10 +1401,12 @@ void MidiInterface<Transport, Settings, Platform>::launchCallback()
@see Thru::Mode @see Thru::Mode
*/ */
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::setThruFilterMode(Thru::Mode inThruFilterMode) inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::setThruFilterMode(Thru::Mode inThruFilterMode)
{ {
mThruFilterMode = inThruFilterMode; mThruFilterMode = inThruFilterMode;
mThruActivated = mThruFilterMode != Thru::Off; mThruActivated = mThruFilterMode != Thru::Off;
return *this;
} }
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
@ -1380,17 +1422,21 @@ inline bool MidiInterface<Transport, Settings, Platform>::getThruState() const
} }
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::turnThruOn(Thru::Mode inThruFilterMode) inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::turnThruOn(Thru::Mode inThruFilterMode)
{ {
mThruActivated = true; mThruActivated = true;
mThruFilterMode = inThruFilterMode; mThruFilterMode = inThruFilterMode;
return *this;
} }
template<class Transport, class Settings, class Platform> template<class Transport, class Settings, class Platform>
inline void MidiInterface<Transport, Settings, Platform>::turnThruOff() inline MidiInterface<Transport, Settings, Platform>& MidiInterface<Transport, Settings, Platform>::turnThruOff()
{ {
mThruActivated = false; mThruActivated = false;
mThruFilterMode = Thru::Off; mThruFilterMode = Thru::Off;
return *this;
} }