Control Surface main
MIDI Control Surface library for Arduino
Loading...
Searching...
No Matches
MIDI_Callbacks.hpp
Go to the documentation of this file.
1#pragma once
2
5
7
9
10// LCOV_EXCL_START
11
30
31// LCOV_EXCL_STOP
32
33template <class Derived>
35 protected:
39 // clang-format off
40 void onNoteOff(Channel channel, uint8_t note, uint8_t velocity, Cable cable);
41 void onNoteOn(Channel channel, uint8_t note, uint8_t velocity, Cable cable);
47 void onSystemExclusive(SysExMessage message);
48 void onTimeCodeQuarterFrame(uint8_t data, Cable cable);
51 void onTuneRequest(Cable cable);
52 void onClock(Cable cable);
53 void onStart(Cable cable);
54 void onContinue(Cable cable);
55 void onStop(Cable cable);
56 void onActiveSensing(Cable cable);
57 void onSystemReset(Cable cable);
58 // clang-format on
60
62 using MMT = MIDIMessageType;
63 switch (msg.getMessageType()) {
64 case MMT::None: break;
65 case MMT::NoteOff:
66 CRTP(Derived).onNoteOff(msg.getChannel(), msg.getData1(),
67 msg.getData2(), msg.getCable());
68 break;
69 case MMT::NoteOn:
70 CRTP(Derived).onNoteOn(msg.getChannel(), msg.getData1(),
71 msg.getData2(), msg.getCable());
72 break;
73 case MMT::KeyPressure:
74 CRTP(Derived).onKeyPressure(msg.getChannel(), msg.getData1(),
75 msg.getData2(), msg.getCable());
76 break;
77 case MMT::ControlChange:
78 CRTP(Derived).onControlChange(msg.getChannel(), msg.getData1(),
79 msg.getData2(), msg.getCable());
80 break;
81 case MMT::ProgramChange:
82 CRTP(Derived).onProgramChange(msg.getChannel(), msg.getData1(),
83 msg.getCable());
84 break;
85 case MMT::ChannelPressure:
86 CRTP(Derived).onChannelPressure(msg.getChannel(),
87 msg.getData1(), msg.getCable());
88 break;
89 case MMT::PitchBend:
90 CRTP(Derived).onPitchBend(msg.getChannel(), msg.getData14bit(),
91 msg.getCable());
92 break;
93 case MMT::SysExStart:
94 case MMT::MTCQuarterFrame:
95 case MMT::SongPositionPointer:
96 case MMT::SongSelect:
97 case MMT::UndefinedSysCommon1:
98 case MMT::UndefinedSysCommon2:
99 case MMT::TuneRequest:
100 case MMT::SysExEnd:
101 case MMT::TimingClock:
102 case MMT::UndefinedRealTime1:
103 case MMT::Start:
104 case MMT::Continue:
105 case MMT::Stop:
106 case MMT::UndefinedRealTime2:
107 case MMT::ActiveSensing:
108 case MMT::SystemReset:
109 default: break;
110 }
111 }
112
114 CRTP(Derived).onSystemExclusive(msg);
115 }
116
118 using MMT = MIDIMessageType;
119 switch (msg.getMessageType()) {
120 case MMT::None: break;
121 case MMT::NoteOff:
122 case MMT::NoteOn:
123 case MMT::KeyPressure:
124 case MMT::ControlChange:
125 case MMT::ProgramChange:
126 case MMT::ChannelPressure:
127 case MMT::PitchBend:
128 case MMT::SysExStart: break;
129 case MMT::MTCQuarterFrame:
130 CRTP(Derived).onTimeCodeQuarterFrame(msg.getData1(),
131 msg.getCable());
132 break;
133 case MMT::SongPositionPointer:
134 CRTP(Derived).onSongPosition(msg.getData14bit(),
135 msg.getCable());
136 break;
137 case MMT::SongSelect:
138 CRTP(Derived).onSongSelect(msg.getData1(), msg.getCable());
139 break;
140 case MMT::UndefinedSysCommon1: break;
141 case MMT::UndefinedSysCommon2: break;
142 case MMT::TuneRequest:
143 CRTP(Derived).onTuneRequest(msg.getCable());
144 break;
145 case MMT::SysExEnd:
146 case MMT::TimingClock:
147 case MMT::UndefinedRealTime1:
148 case MMT::Start:
149 case MMT::Continue:
150 case MMT::Stop:
151 case MMT::UndefinedRealTime2:
152 case MMT::ActiveSensing:
153 case MMT::SystemReset:
154 default: break;
155 }
156 }
157
159 using MMT = MIDIMessageType;
160 switch (msg.getMessageType()) {
161 case MMT::None: break;
162 case MMT::NoteOff:
163 case MMT::NoteOn:
164 case MMT::KeyPressure:
165 case MMT::ControlChange:
166 case MMT::ProgramChange:
167 case MMT::ChannelPressure:
168 case MMT::PitchBend:
169 case MMT::SysExStart:
170 case MMT::MTCQuarterFrame:
171 case MMT::SongPositionPointer:
172 case MMT::SongSelect:
173 case MMT::UndefinedSysCommon1:
174 case MMT::UndefinedSysCommon2:
175 case MMT::TuneRequest:
176 case MMT::SysExEnd: break;
177 case MMT::TimingClock: CRTP(Derived).onClock(msg.getCable()); break;
178 case MMT::UndefinedRealTime1: break;
179 case MMT::Start: CRTP(Derived).onStart(msg.getCable()); break;
180 case MMT::Continue: CRTP(Derived).onContinue(msg.getCable()); break;
181 case MMT::Stop: CRTP(Derived).onStop(msg.getCable()); break;
182 case MMT::UndefinedRealTime2: break;
183 case MMT::ActiveSensing:
184 CRTP(Derived).onActiveSensing(msg.getCable());
185 break;
186 case MMT::SystemReset:
187 CRTP(Derived).onSystemReset(msg.getCable());
188 break;
189 default: break;
190 }
191 }
192
194
195 template <class...>
196 struct Dummy {};
197
198 template <class T1, class R1, class... Args1, //
199 class T2, class R2, class... Args2>
200 static constexpr bool same_return_type_and_arguments(R1 (T1::*)(Args1...),
201 R2 (T2::*)(Args2...)) {
202 return std::is_same<Dummy<R1, Args1...>, Dummy<R2, Args2...>>::value;
203 }
204
205 public:
207 // clang-format off
208 static_assert(std::is_base_of<FineGrainedMIDI_Callbacks, Derived>::value, "Invalid CRTP");
209 static_assert(same_return_type_and_arguments(&Derived::onNoteOff, &FineGrainedMIDI_Callbacks::onNoteOff), "Incorrect signature for onNoteOff");
210 static_assert(same_return_type_and_arguments(&Derived::onNoteOn, &FineGrainedMIDI_Callbacks::onNoteOn), "Incorrect signature for onNoteOn");
211 static_assert(same_return_type_and_arguments(&Derived::onKeyPressure, &FineGrainedMIDI_Callbacks::onKeyPressure), "Incorrect signature for onKeyPressure");
212 static_assert(same_return_type_and_arguments(&Derived::onControlChange, &FineGrainedMIDI_Callbacks::onControlChange), "Incorrect signature for onControlChange");
213 static_assert(same_return_type_and_arguments(&Derived::onProgramChange, &FineGrainedMIDI_Callbacks::onProgramChange), "Incorrect signature for onProgramChange");
214 static_assert(same_return_type_and_arguments(&Derived::onChannelPressure, &FineGrainedMIDI_Callbacks::onChannelPressure), "Incorrect signature for onChannelPressure");
215 static_assert(same_return_type_and_arguments(&Derived::onPitchBend, &FineGrainedMIDI_Callbacks::onPitchBend), "Incorrect signature for onPitchBend");
216 static_assert(same_return_type_and_arguments(&Derived::onSystemExclusive, &FineGrainedMIDI_Callbacks::onSystemExclusive), "Incorrect signature for onSystemExclusive");
217 static_assert(same_return_type_and_arguments(&Derived::onTimeCodeQuarterFrame, &FineGrainedMIDI_Callbacks::onTimeCodeQuarterFrame), "Incorrect signature for onTimeCodeQuarterFrame");
218 static_assert(same_return_type_and_arguments(&Derived::onSongPosition, &FineGrainedMIDI_Callbacks::onSongPosition), "Incorrect signature for onSongPosition");
219 static_assert(same_return_type_and_arguments(&Derived::onSongSelect, &FineGrainedMIDI_Callbacks::onSongSelect), "Incorrect signature for onSongSelect");
220 static_assert(same_return_type_and_arguments(&Derived::onTuneRequest, &FineGrainedMIDI_Callbacks::onTuneRequest), "Incorrect signature for onTuneRequest");
221 static_assert(same_return_type_and_arguments(&Derived::onClock, &FineGrainedMIDI_Callbacks::onClock), "Incorrect signature for onClock");
222 static_assert(same_return_type_and_arguments(&Derived::onStart, &FineGrainedMIDI_Callbacks::onStart), "Incorrect signature for onStart");
223 static_assert(same_return_type_and_arguments(&Derived::onContinue, &FineGrainedMIDI_Callbacks::onContinue), "Incorrect signature for onContinue");
224 static_assert(same_return_type_and_arguments(&Derived::onStop, &FineGrainedMIDI_Callbacks::onStop), "Incorrect signature for onStop");
225 static_assert(same_return_type_and_arguments(&Derived::onActiveSensing, &FineGrainedMIDI_Callbacks::onActiveSensing), "Incorrect signature for onActiveSensing");
226 static_assert(same_return_type_and_arguments(&Derived::onSystemReset, &FineGrainedMIDI_Callbacks::onSystemReset), "Incorrect signature for onSystemReset");
227 // clang-format on
228 }
229
231};
232
233// clang-format off
244template <class Derived> inline void FineGrainedMIDI_Callbacks<Derived>::onSongSelect(uint8_t,Cable) {}
245template <class Derived> inline void FineGrainedMIDI_Callbacks<Derived>::onTuneRequest(Cable) {}
246template <class Derived> inline void FineGrainedMIDI_Callbacks<Derived>::onClock(Cable) {}
247template <class Derived> inline void FineGrainedMIDI_Callbacks<Derived>::onStart(Cable) {}
248template <class Derived> inline void FineGrainedMIDI_Callbacks<Derived>::onContinue(Cable) {}
249template <class Derived> inline void FineGrainedMIDI_Callbacks<Derived>::onStop(Cable) {}
250template <class Derived> inline void FineGrainedMIDI_Callbacks<Derived>::onActiveSensing(Cable) {}
251template <class Derived> inline void FineGrainedMIDI_Callbacks<Derived>::onSystemReset(Cable) {}
252// clang-format on
253
#define CRTP(Derived)
Helper for the Curiously Recurring Template Pattern.
Definition CRTP.hpp:4
MIDIMessageType
All possible MIDI status byte values (without channel).
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
A type-safe class for MIDI USB Cable numbers.
Definition Cable.hpp:13
A type-safe class for MIDI channels.
Definition Channel.hpp:13
void onChannelMessage(MIDI_Interface &, ChannelMessage msg) override
Callback for incoming MIDI Channel Messages (notes, control change, pitch bend, etc....
void onTimeCodeQuarterFrame(uint8_t data, Cable cable)
void onPitchBend(Channel channel, uint16_t bend, Cable cable)
void onSysCommonMessage(MIDI_Interface &, SysCommonMessage msg) override
Callback for incoming MIDI System Common Messages.
void onSystemReset(Cable cable)
void onSystemExclusive(SysExMessage message)
void onActiveSensing(Cable cable)
void onProgramChange(Channel channel, uint8_t program, Cable cable)
void onNoteOff(Channel channel, uint8_t note, uint8_t velocity, Cable cable)
void onRealTimeMessage(MIDI_Interface &, RealTimeMessage msg) override
Callback for incoming MIDI Real-Time Messages.
void onNoteOn(Channel channel, uint8_t note, uint8_t velocity, Cable cable)
void onControlChange(Channel channel, uint8_t controller, uint8_t value, Cable cable)
void onSongPosition(uint16_t beats, Cable cable)
void onTuneRequest(Cable cable)
void onSongSelect(uint8_t songnumber, Cable cable)
void onKeyPressure(Channel channel, uint8_t note, uint8_t pressure, Cable cable)
void onSysExMessage(MIDI_Interface &, SysExMessage msg) override
Callback for incoming MIDI System Exclusive Messages.
void onChannelPressure(Channel channel, uint8_t pressure, Cable cable)
A class for callbacks from MIDI input.
virtual void onChannelMessage(MIDI_Interface &, ChannelMessage)
Callback for incoming MIDI Channel Messages (notes, control change, pitch bend, etc....
virtual ~MIDI_Callbacks()=default
Destructor.
virtual void onSysExMessage(MIDI_Interface &, SysExMessage)
Callback for incoming MIDI System Exclusive Messages.
virtual void onRealTimeMessage(MIDI_Interface &, RealTimeMessage)
Callback for incoming MIDI Real-Time Messages.
virtual void onSysCommonMessage(MIDI_Interface &, SysCommonMessage)
Callback for incoming MIDI System Common Messages.
An abstract class for MIDI interfaces.
An array wrapper for easy copying, comparing, and iterating.
Definition Array.hpp:32