Template settings.

This commit is contained in:
Francois Best 2014-04-20 17:23:10 +02:00
parent d13353a5b6
commit 410e51c91a
4 changed files with 228 additions and 195 deletions

View File

@ -40,7 +40,7 @@ the hardware interface, meaning you can use HardwareSerial, SoftwareSerial
or ak47's Uart classes. The only requirement is that the class implements
the begin, read, write and available methods.
*/
template<class SerialPort>
template<class SerialPort, class Settings = DefaultSettings>
class MidiInterface
{
public:

View File

@ -26,8 +26,8 @@
BEGIN_MIDI_NAMESPACE
/// \brief Constructor for MidiInterface.
template<class SerialPort>
MidiInterface<SerialPort>::MidiInterface(SerialPort& inSerial)
template<class SerialPort, class Settings>
inline MidiInterface<SerialPort, Settings>::MidiInterface(SerialPort& inSerial)
: mSerial(inSerial)
{
#if MIDI_BUILD_INPUT && MIDI_USE_CALLBACKS
@ -56,8 +56,8 @@ MidiInterface<SerialPort>::MidiInterface(SerialPort& inSerial)
This is not really useful for the Arduino, as it is never called...
*/
template<class SerialPort>
MidiInterface<SerialPort>::~MidiInterface()
template<class SerialPort, class Settings>
inline MidiInterface<SerialPort, Settings>::~MidiInterface()
{
}
@ -69,21 +69,22 @@ MidiInterface<SerialPort>::~MidiInterface()
- Input channel set to 1 if no value is specified
- Full thru mirroring
*/
template<class SerialPort>
void MidiInterface<SerialPort>::begin(Channel inChannel)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::begin(Channel inChannel)
{
// Initialise the Serial port
#if defined(ARDUINO)
mSerial.begin(MIDI_BAUDRATE);
#elif defined(FSE_AVR)
mSerial. template open<MIDI_BAUDRATE>();
#if defined(FSE_AVR)
mSerial. template open<Settings::BaudRate>();
#else
mSerial.begin(Settings::BaudRate);
#endif
#if MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS
#if MIDI_BUILD_OUTPUT
if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType;
#endif // MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS
}
#endif // MIDI_BUILD_OUTPUT
#if MIDI_BUILD_INPUT
@ -133,8 +134,8 @@ void MidiInterface<SerialPort>::begin(Channel inChannel)
This is an internal method, use it only if you need to send raw data
from your code, at your own risks.
*/
template<class SerialPort>
void MidiInterface<SerialPort>::send(MidiType inType,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::send(MidiType inType,
DataByte inData1,
DataByte inData2,
Channel inChannel)
@ -144,11 +145,10 @@ void MidiInterface<SerialPort>::send(MidiType inType,
inChannel == MIDI_CHANNEL_OMNI ||
inType < NoteOff)
{
#if MIDI_USE_RUNNING_STATUS
if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType;
#endif
}
return; // Don't send anything
}
@ -160,18 +160,20 @@ void MidiInterface<SerialPort>::send(MidiType inType,
const StatusByte status = getStatus(inType, inChannel);
#if MIDI_USE_RUNNING_STATUS
// Check Running Status
if (Settings::UseRunningStatus)
{
if (mRunningStatus_TX != status)
{
// New message, memorise and send header
mRunningStatus_TX = status;
mSerial.write(mRunningStatus_TX);
}
#else
}
else
{
// Don't care about running status, send the status byte.
mSerial.write(status);
#endif
}
// Then send data
mSerial.write(inData1);
@ -195,8 +197,8 @@ void MidiInterface<SerialPort>::send(MidiType inType,
Take a look at the values, names and frequencies of notes here:
http://www.phys.unsw.edu.au/jw/notes.html
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendNoteOn(DataByte inNoteNumber,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendNoteOn(DataByte inNoteNumber,
DataByte inVelocity,
Channel inChannel)
{
@ -214,8 +216,8 @@ void MidiInterface<SerialPort>::sendNoteOn(DataByte inNoteNumber,
Take a look at the values, names and frequencies of notes here:
http://www.phys.unsw.edu.au/jw/notes.html
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendNoteOff(DataByte inNoteNumber,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendNoteOff(DataByte inNoteNumber,
DataByte inVelocity,
Channel inChannel)
{
@ -226,8 +228,8 @@ void MidiInterface<SerialPort>::sendNoteOff(DataByte inNoteNumber,
\param inProgramNumber The Program to select (0 to 127).
\param inChannel The channel on which the message will be sent (1 to 16).
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendProgramChange(DataByte inProgramNumber,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendProgramChange(DataByte inProgramNumber,
Channel inChannel)
{
send(ProgramChange, inProgramNumber, 0, inChannel);
@ -239,8 +241,8 @@ void MidiInterface<SerialPort>::sendProgramChange(DataByte inProgramNumber,
\param inChannel The channel on which the message will be sent (1 to 16).
@see MidiControlChangeNumber
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendControlChange(DataByte inControlNumber,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendControlChange(DataByte inControlNumber,
DataByte inControlValue,
Channel inChannel)
{
@ -252,8 +254,8 @@ void MidiInterface<SerialPort>::sendControlChange(DataByte inControlNumber,
\param inPressure The amount of AfterTouch to apply (0 to 127).
\param inChannel The channel on which the message will be sent (1 to 16).
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendPolyPressure(DataByte inNoteNumber,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendPolyPressure(DataByte inNoteNumber,
DataByte inPressure,
Channel inChannel)
{
@ -264,8 +266,8 @@ void MidiInterface<SerialPort>::sendPolyPressure(DataByte inNoteNumber,
\param inPressure The amount of AfterTouch to apply to all notes.
\param inChannel The channel on which the message will be sent (1 to 16).
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendAfterTouch(DataByte inPressure,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendAfterTouch(DataByte inPressure,
Channel inChannel)
{
send(AfterTouchChannel, inPressure, 0, inChannel);
@ -277,8 +279,8 @@ void MidiInterface<SerialPort>::sendAfterTouch(DataByte inPressure,
center value is 0.
\param inChannel The channel on which the message will be sent (1 to 16).
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendPitchBend(int inPitchValue,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendPitchBend(int inPitchValue,
Channel inChannel)
{
const unsigned bend = inPitchValue - MIDI_PITCHBEND_MIN;
@ -292,11 +294,11 @@ void MidiInterface<SerialPort>::sendPitchBend(int inPitchValue,
and +1.0f (max upwards bend), center value is 0.0f.
\param inChannel The channel on which the message will be sent (1 to 16).
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendPitchBend(double inPitchValue,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendPitchBend(double inPitchValue,
Channel inChannel)
{
const int value = inPitchValue * MIDI_PITCHBEND_MAX;
const int value = inPitchValue * MIDI_PITCHBEND_MAX * Settings::Toto;
sendPitchBend(value, inChannel);
}
@ -309,29 +311,32 @@ void MidiInterface<SerialPort>::sendPitchBend(double inPitchValue,
default value for ArrayContainsBoundaries is set to 'false' for compatibility
with previous versions of the library.
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendSysEx(unsigned inLength,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendSysEx(unsigned inLength,
const byte* inArray,
bool inArrayContainsBoundaries)
{
if (inArrayContainsBoundaries == false)
const bool writeBeginEndBytes = !inArrayContainsBoundaries;
if (writeBeginEndBytes)
{
mSerial.write(0xf0);
}
for (unsigned i = 0; i < inLength; ++i)
{
mSerial.write(inArray[i]);
}
if (writeBeginEndBytes)
{
mSerial.write(0xf7);
}
else
{
for (unsigned i = 0; i < inLength; ++i)
mSerial.write(inArray[i]);
}
#if MIDI_USE_RUNNING_STATUS
if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType;
#endif
}
}
/*! \brief Send a Tune Request message.
@ -339,8 +344,8 @@ void MidiInterface<SerialPort>::sendSysEx(unsigned inLength,
When a MIDI unit receives this message,
it should tune its oscillators (if equipped with any).
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendTuneRequest()
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendTuneRequest()
{
sendRealTime(TuneRequest);
}
@ -351,8 +356,8 @@ void MidiInterface<SerialPort>::sendTuneRequest()
\param inValuesNibble MTC data
See MIDI Specification for more information.
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
DataByte inValuesNibble)
{
const byte data = (((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f));
@ -365,42 +370,45 @@ void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
\param inData if you want to encode directly the nibbles in your program,
you can send the byte here.
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inData)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendTimeCodeQuarterFrame(DataByte inData)
{
mSerial.write((byte)TimeCodeQuarterFrame);
mSerial.write(inData);
#if MIDI_USE_RUNNING_STATUS
if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType;
#endif
}
}
/*! \brief Send a Song Position Pointer message.
\param inBeats The number of beats since the start of the song.
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendSongPosition(unsigned inBeats)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendSongPosition(unsigned inBeats)
{
mSerial.write((byte)SongPosition);
mSerial.write(inBeats & 0x7f);
mSerial.write((inBeats >> 7) & 0x7f);
#if MIDI_USE_RUNNING_STATUS
if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType;
#endif
}
}
/*! \brief Send a Song Select message */
template<class SerialPort>
void MidiInterface<SerialPort>::sendSongSelect(DataByte inSongNumber)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendSongSelect(DataByte inSongNumber)
{
mSerial.write((byte)SongSelect);
mSerial.write(inSongNumber & 0x7f);
#if MIDI_USE_RUNNING_STATUS
if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType;
#endif
}
}
/*! \brief Send a Real Time (one byte) message.
@ -410,8 +418,8 @@ void MidiInterface<SerialPort>::sendSongSelect(DataByte inSongNumber)
You can also send a Tune Request with this method.
@see MidiType
*/
template<class SerialPort>
void MidiInterface<SerialPort>::sendRealTime(MidiType inType)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::sendRealTime(MidiType inType)
{
switch (inType)
{
@ -432,17 +440,18 @@ void MidiInterface<SerialPort>::sendRealTime(MidiType inType)
// Do not cancel Running Status for real-time messages as they can be
// interleaved within any message. Though, TuneRequest can be sent here,
// and as it is a System Common message, it must reset Running Status.
#if MIDI_USE_RUNNING_STATUS
if (inType == TuneRequest) mRunningStatus_TX = InvalidType;
#endif
if (Settings::UseRunningStatus && inType == TuneRequest)
{
mRunningStatus_TX = InvalidType;
}
}
/*! @} */ // End of doc group MIDI Output
// -----------------------------------------------------------------------------
template<class SerialPort>
StatusByte MidiInterface<SerialPort>::getStatus(MidiType inType,
template<class SerialPort, class Settings>
StatusByte MidiInterface<SerialPort, Settings>::getStatus(MidiType inType,
Channel inChannel) const
{
return ((byte)inType | ((inChannel - 1) & 0x0f));
@ -469,16 +478,16 @@ StatusByte MidiInterface<SerialPort>::getStatus(MidiType inType,
it is sent back on the MIDI output.
@see see setInputChannel()
*/
template<class SerialPort>
inline bool MidiInterface<SerialPort>::read()
template<class SerialPort, class Settings>
inline bool MidiInterface<SerialPort, Settings>::read()
{
return read(mInputChannel);
}
/*! \brief Read messages on a specified channel.
*/
template<class SerialPort>
inline bool MidiInterface<SerialPort>::read(Channel inChannel)
template<class SerialPort, class Settings>
inline bool MidiInterface<SerialPort, Settings>::read(Channel inChannel)
{
if (inChannel >= MIDI_CHANNEL_OFF)
return false; // MIDI Input disabled.
@ -506,8 +515,8 @@ inline bool MidiInterface<SerialPort>::read(Channel inChannel)
// -----------------------------------------------------------------------------
// Private method: MIDI parser
template<class SerialPort>
bool MidiInterface<SerialPort>::parse()
template<class SerialPort, class Settings>
bool MidiInterface<SerialPort, Settings>::parse()
{
if (mSerial.available() == 0)
// No data available.
@ -770,24 +779,26 @@ bool MidiInterface<SerialPort>::parse()
// Then update the index of the pending message.
mPendingMessageIndex++;
#if USE_1BYTE_PARSING
if (Settings::Use1ByteParsing)
{
// Message is not complete.
return false;
#else
// Call the parser recursively
// to parse the rest of the message.
}
else
{
// Call the parser recursively to parse the rest of the message.
return parse();
#endif
}
}
}
}
// Private method, see midi_Settings.h for documentation
template<class SerialPort>
inline void MidiInterface<SerialPort>::handleNullVelocityNoteOnAsNoteOff()
template<class SerialPort, class Settings>
inline void MidiInterface<SerialPort, Settings>::handleNullVelocityNoteOnAsNoteOff()
{
#if MIDI_HANDLE_NULL_VELOCITY_NOTE_ON_AS_NOTE_OFF
if (getType() == NoteOn && getData2() == 0)
if (Settings::HandleNullVelocityNoteOnAsNoteOff &&
getType() == NoteOn && getData2() == 0)
{
mMessage.type = NoteOff;
}
@ -795,8 +806,8 @@ inline void MidiInterface<SerialPort>::handleNullVelocityNoteOnAsNoteOff()
}
// Private method: check if the received message is on the listened channel
template<class SerialPort>
inline bool MidiInterface<SerialPort>::inputFilter(Channel inChannel)
template<class SerialPort, class Settings>
inline bool MidiInterface<SerialPort, Settings>::inputFilter(Channel inChannel)
{
// This method handles recognition of channel
// (to know if the message is destinated to the Arduino)
@ -827,8 +838,8 @@ inline bool MidiInterface<SerialPort>::inputFilter(Channel inChannel)
}
// Private method: reset input attributes
template<class SerialPort>
inline void MidiInterface<SerialPort>::resetInput()
template<class SerialPort, class Settings>
inline void MidiInterface<SerialPort, Settings>::resetInput()
{
mPendingMessageIndex = 0;
mPendingMessageExpectedLenght = 0;
@ -841,8 +852,8 @@ inline void MidiInterface<SerialPort>::resetInput()
Returns an enumerated type. @see MidiType
*/
template<class SerialPort>
MidiType MidiInterface<SerialPort>::getType() const
template<class SerialPort, class Settings>
MidiType MidiInterface<SerialPort, Settings>::getType() const
{
return mMessage.type;
}
@ -852,22 +863,22 @@ MidiType MidiInterface<SerialPort>::getType() const
\return Channel range is 1 to 16.
For non-channel messages, this will return 0.
*/
template<class SerialPort>
Channel MidiInterface<SerialPort>::getChannel() const
template<class SerialPort, class Settings>
Channel MidiInterface<SerialPort, Settings>::getChannel() const
{
return mMessage.channel;
}
/*! \brief Get the first data byte of the last received message. */
template<class SerialPort>
DataByte MidiInterface<SerialPort>::getData1() const
template<class SerialPort, class Settings>
DataByte MidiInterface<SerialPort, Settings>::getData1() const
{
return mMessage.data1;
}
/*! \brief Get the second data byte of the last received message. */
template<class SerialPort>
DataByte MidiInterface<SerialPort>::getData2() const
template<class SerialPort, class Settings>
DataByte MidiInterface<SerialPort, Settings>::getData2() const
{
return mMessage.data2;
}
@ -876,8 +887,8 @@ DataByte MidiInterface<SerialPort>::getData2() const
@see getSysExArrayLength to get the array's length in bytes.
*/
template<class SerialPort>
const byte* MidiInterface<SerialPort>::getSysExArray() const
template<class SerialPort, class Settings>
const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
{
return mMessage.sysexArray;
}
@ -887,24 +898,25 @@ const byte* MidiInterface<SerialPort>::getSysExArray() const
It is coded using data1 as LSB and data2 as MSB.
\return The array's length, in bytes.
*/
template<class SerialPort>
unsigned MidiInterface<SerialPort>::getSysExArrayLength() const
template<class SerialPort, class Settings>
unsigned MidiInterface<SerialPort, Settings>::getSysExArrayLength() const
{
const unsigned size = ((unsigned)(mMessage.data2) << 8) | mMessage.data1;
return (size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : size;
static const unsigned maxSize = Settings::SysExArraySize;
const unsigned size = (unsigned(mMessage.data2) << 8) | mMessage.data1;
return (size > maxSize) ? maxSize : size;
}
/*! \brief Check if a valid message is stored in the structure. */
template<class SerialPort>
bool MidiInterface<SerialPort>::check() const
template<class SerialPort, class Settings>
bool MidiInterface<SerialPort, Settings>::check() const
{
return mMessage.valid;
}
// -----------------------------------------------------------------------------
template<class SerialPort>
Channel MidiInterface<SerialPort>::getInputChannel() const
template<class SerialPort, class Settings>
Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
{
return mInputChannel;
}
@ -913,8 +925,8 @@ Channel MidiInterface<SerialPort>::getInputChannel() const
\param inChannel the channel value. Valid values are 1 to 16, MIDI_CHANNEL_OMNI
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
*/
template<class SerialPort>
void MidiInterface<SerialPort>::setInputChannel(Channel inChannel)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::setInputChannel(Channel inChannel)
{
mInputChannel = inChannel;
}
@ -926,8 +938,8 @@ void MidiInterface<SerialPort>::setInputChannel(Channel inChannel)
This is a utility static method, used internally,
made public so you can handle MidiTypes more easily.
*/
template<class SerialPort>
MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
template<class SerialPort, class Settings>
MidiType MidiInterface<SerialPort, Settings>::getTypeFromStatusByte(byte inStatus)
{
if ((inStatus < 0x80) ||
(inStatus == 0xf4) ||
@ -949,14 +961,14 @@ MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
/*! \brief Returns channel in the range 1-16
*/
template<class SerialPort>
inline Channel MidiInterface<SerialPort>::getChannelFromStatusByte(byte inStatus)
template<class SerialPort, class Settings>
inline Channel MidiInterface<SerialPort, Settings>::getChannelFromStatusByte(byte inStatus)
{
return (inStatus & 0x0f) + 1;
}
template<class SerialPort>
bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
template<class SerialPort, class Settings>
bool MidiInterface<SerialPort, Settings>::isChannelMessage(MidiType inType)
{
return (inType == NoteOff ||
inType == NoteOn ||
@ -975,24 +987,24 @@ bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
@{
*/
template<class SerialPort> void MidiInterface<SerialPort>::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemExclusive(void (*fptr)(byte* array, byte size)) { mSystemExclusiveCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSongPosition(void (*fptr)(unsigned beats)) { mSongPositionCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSystemExclusive(void (*fptr)(byte* array, byte size)) { mSystemExclusiveCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongPosition(void (*fptr)(unsigned beats)) { mSongPositionCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; }
/*! \brief Detach an external function from the given type.
@ -1000,8 +1012,8 @@ template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemReset(
\param inType The type of message to unbind.
When a message of this type is received, no function will be called.
*/
template<class SerialPort>
void MidiInterface<SerialPort>::disconnectCallbackFromType(MidiType inType)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::disconnectCallbackFromType(MidiType inType)
{
switch (inType)
{
@ -1031,8 +1043,8 @@ void MidiInterface<SerialPort>::disconnectCallbackFromType(MidiType inType)
/*! @} */ // End of doc group MIDI Callbacks
// Private - launch callback function based on received type.
template<class SerialPort>
void MidiInterface<SerialPort>::launchCallback()
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::launchCallback()
{
// The order is mixed to allow frequent messages to trigger their callback faster.
switch (mMessage.type)
@ -1092,8 +1104,8 @@ void MidiInterface<SerialPort>::launchCallback()
@see MidiFilterMode
*/
template<class SerialPort>
void MidiInterface<SerialPort>::setThruFilterMode(MidiFilterMode inThruFilterMode)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::setThruFilterMode(MidiFilterMode inThruFilterMode)
{
mThruFilterMode = inThruFilterMode;
if (mThruFilterMode != Off)
@ -1102,27 +1114,27 @@ void MidiInterface<SerialPort>::setThruFilterMode(MidiFilterMode inThruFilterMod
mThruActivated = false;
}
template<class SerialPort>
MidiFilterMode MidiInterface<SerialPort>::getFilterMode() const
template<class SerialPort, class Settings>
MidiFilterMode MidiInterface<SerialPort, Settings>::getFilterMode() const
{
return mThruFilterMode;
}
template<class SerialPort>
bool MidiInterface<SerialPort>::getThruState() const
template<class SerialPort, class Settings>
bool MidiInterface<SerialPort, Settings>::getThruState() const
{
return mThruActivated;
}
template<class SerialPort>
void MidiInterface<SerialPort>::turnThruOn(MidiFilterMode inThruFilterMode)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::turnThruOn(MidiFilterMode inThruFilterMode)
{
mThruActivated = true;
mThruFilterMode = inThruFilterMode;
}
template<class SerialPort>
void MidiInterface<SerialPort>::turnThruOff()
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::turnThruOff()
{
mThruActivated = false;
mThruFilterMode = Off;
@ -1136,8 +1148,8 @@ void MidiInterface<SerialPort>::turnThruOff()
// to output unless filter is set to Off.
// - Channel messages are passed to the output whether their channel
// is matching the input channel and the filter setting
template<class SerialPort>
void MidiInterface<SerialPort>::thruFilter(Channel inChannel)
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::thruFilter(Channel inChannel)
{
// If the feature is disabled, don't do anything.
if (!mThruActivated || (mThruFilterMode == Off))

View File

@ -207,11 +207,12 @@ struct Message
#define MIDI_CREATE_INSTANCE(Type, SerialPort, Name) \
midi::MidiInterface<Type> Name((Type&)SerialPort);
/*! \brief Shortcut for MIDI Interface class with template argument.
The class name for a MIDI object using the hardware UART would be
midi::MidiInterface<HardwareSerial>, when the macro is MIDI_CLASS(HardwareSerial).
/*! \brief Create an instance of the library attached to a serial port with
custom settings.
@see DefaultSettings
@see MIDI_CREATE_INSTANCE
*/
#define MIDI_CLASS(Type) \
midi::MidiInterface<Type>
#define MIDI_CREATE_CUSTOM_INSTANCE(Type, SerialPort, Name, Settings) \
midi::MidiInterface<Type, Settings> Name((Type&)SerialPort);
END_MIDI_NAMESPACE

View File

@ -99,4 +99,24 @@
BEGIN_MIDI_NAMESPACE
/*! \brief Default Settings Traits struct
To change the default settings, don't edit them there, create a subclass and
override the values in that subclass, then use the MIDI_CREATE_CUSTOM_INSTANCE
macro to create your instance. The settings you don't override will keep their
default value. Eg:
struct MySettings : public midi::DefaultSettings
{
static const bool UseRunningStatus = false; // Messes with my old equipment!
};
MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial2, midi, MySettings);
*/
struct DefaultSettings
{
static const bool UseRunningStatus = true;
static const bool HandleNullVelocityNoteOnAsNoteOff = true;
static const bool Use1ByteParsing = true;
static const unsigned BaudRate = 31250;
static const unsigned SysExArraySize = 128;
};
END_MIDI_NAMESPACE