BuGUI
BUtton Grid User Interface
Loading...
Searching...
No Matches
midi_formater.hpp
1#pragma once
2#include <bugui/concepts/color.hpp>
3#include <bugui/concepts/protocol.hpp>
4#include <bugui/color/color_converter.hpp>
5
6#include <libremidi/libremidi.hpp>
7
8namespace bugui
9{
14template <is_sysex_out_component Component>
16{
17 static consteval auto prefix_size()
18 { return Component::out_message_t::sysex_id().size() + 1; };
19 static consteval auto prefix_incremented()
20 { return prefix_size() + 1; };
21};
22
26template <typename Component>
27struct base_midi_formater
28{
31 virtual void set(uint8_t id
32 , const color_converter
33 <typename Component::color_t>& converter)
34 {
36 if (bytes.size() == sysex_formater<Component>
37 ::prefix_size())
38 bytes.push_back(Component::color_t::constant_id());
39
40 bytes.push_back(id);
41 bytes.push_back(converter.get());
42 };
43
48 void add(uint8_t element) { bytes.push_back(element); }
49
53 virtual void clear()
54 {
56 bytes.erase(bytes.cbegin() +
57 sysex_formater<Component>::prefix_size()
58 , bytes.cend());
59 else
60 bytes.erase(bytes.cbegin() + 1, bytes.cend());
61 }
62
65 bool has_message() const
66 {
68 return bytes.size() >
69 sysex_formater<Component>::prefix_size();
70 else
71 return bytes.size() > 1;
72 }
73
75 const libremidi::midi_bytes& get() const { return bytes; }
76
77protected:
78 explicit base_midi_formater()
79 {
80 using namespace std;
81 using namespace libremidi;
82
84 bytes.push_back(to_underlying(message_type::NOTE_ON));
85
87 bytes.push_back(to_underlying(message_type
88 ::CONTROL_CHANGE));
89
91 {
92 bytes.push_back(to_underlying(message_type
93 ::SYSTEM_EXCLUSIVE));
94
95 for (const auto& id
96 : Component::out_message_t::sysex_id())
97 bytes.push_back(id);
98 }
99 }
100
101 libremidi::midi_bytes bytes;
102};
103
106template <typename Component>
107struct midi_formater final
108 : base_midi_formater<Component>
109{ };
110
115template <has_dual_blink Component>
116struct dual_blinker : virtual base_midi_formater<Component>
117{
121 bool has_blink_message() const
122 {
124 return blink_bytes.size() >
125 sysex_formater<Component>::prefix_incremented();
126 else
127 return blink_bytes.size() > 1;
128 }
129
132 void add_blink(uint8_t element)
133 { blink_bytes.push_back(element); }
134
137 const libremidi::midi_bytes& get_blink() const
138 { return blink_bytes; }
139
140protected:
141 explicit dual_blinker()
142 : base_midi_formater<Component>{}
143 {
144 using namespace std;
145 using namespace libremidi;
146
147 if constexpr(is_on_off_out_component<Component>)
148 blink_bytes.push_back(channel_events::make_command
149 (message_type::NOTE_ON
150 , Component::color_t
151 ::blinking_channel()));
152
153 if constexpr(is_cc_out_component<Component>)
154 blink_bytes.push_back(channel_events::make_command
155 (message_type::CONTROL_CHANGE
156 , Component::color_t
157 ::blinking_channel()));
158
159 if constexpr(is_sysex_out_component<Component>)
160 {
161 blink_bytes = this->bytes;
162 blink_bytes.push_back(Component::color_t::blinking_id());
163 }
164 }
165
166 void clear() override
167 {
169 this->blink_bytes.erase(this->blink_bytes.cbegin() +
171 ::prefix_incremented()
172 , this->blink_bytes.cend());
173 else
174 this->blink_bytes.erase(this->blink_bytes.cbegin() + 1
175 , this->blink_bytes.cend());
176 }
177
178 libremidi::midi_bytes blink_bytes;
179};
180
185template <typename Component>
186 requires (has_dual_blink<Component>
187 && !has_dual_pulse<Component>)
189 : dual_blinker<Component>
190{
191 using color_cnvrtr =
193
194 void set(uint8_t id, const color_cnvrtr& converter) override
195 {
197 if (this->bytes.size() == sysex_formater<Component>
198 ::prefix_size())
199 this->bytes.push_back(Component::color_t::constant_id());
200
201 this->bytes.push_back(id);
202
203 if (converter.get_state() != color::states::constant)
204 {
205 this->blink_bytes.push_back(id);
206 this->bytes.push_back(color_cnvrtr::clear_value);
207 this->blink_bytes.push_back(converter.get());
208 }
209 else
210 this->bytes.push_back(converter.get());
211 }
212
218};
219
224template <has_dual_pulse Component>
225struct dual_pulser : virtual base_midi_formater<Component>
226{
230 bool has_pulse_message() const
231 {
233 return pulse_bytes.size() >
234 sysex_formater<Component>::prefix_incremented();
235 else
236 return pulse_bytes.size() > 1;
237 }
238
241 void add_pulse(uint8_t element)
242 { pulse_bytes.push_back(element); }
243
246 const libremidi::midi_bytes& get_pulse() const
247 { return pulse_bytes; }
248
249protected:
250 explicit dual_pulser()
251 : base_midi_formater<Component>{}
252 {
253 using namespace std;
254 using namespace libremidi;
255
256 if constexpr(is_on_off_out_component<Component>)
257 pulse_bytes.push_back(channel_events::make_command
258 (message_type::NOTE_ON
259 , Component::color_t
260 ::pulsing_channel()));
261
262 if constexpr(is_cc_out_component<Component>)
263 pulse_bytes.push_back(channel_events::make_command
264 (message_type::CONTROL_CHANGE
265 , Component::color_t
266 ::pulsing_channel()));
267
268 if constexpr(is_sysex_out_component<Component>)
269 {
270 pulse_bytes = this->bytes;
271 pulse_bytes.push_back(Component::color_t::pulsing_id());
272 }
273 }
274
275 void clear() override
276 {
278 this->pulse_bytes.erase(this->pulse_bytes.cbegin() +
280 ::prefix_incremented()
281 , this->pulse_bytes.cend());
282 else
283 this->pulse_bytes.erase(this->pulse_bytes.cbegin() + 1
284 , this->pulse_bytes.cend());
285 }
286
287 libremidi::midi_bytes pulse_bytes;
288};
289
294template <typename Component>
295 requires (!has_dual_blink<Component>
296 && has_dual_pulse<Component>)
297struct midi_formater<Component> final
298 : dual_pulser<Component>
299{
300 using color_cnvrtr =
301 color_converter<typename Component::color_t>;
302
303 void set(uint8_t id, const color_cnvrtr& converter) override
304 {
305 if constexpr(is_sysex_out_component<Component>)
306 if (this->bytes.size() == sysex_formater<Component>
307 ::prefix_size())
308 this->bytes.push_back(Component::color_t::constant_id());
309
310 this->bytes.push_back(id);
311
312 if (converter.get_state() != color::states::constant)
313 {
314 this->bytes.push_back(color_cnvrtr::clear_value);
315 this->pulse_bytes.push_back(converter.get());
316 this->pulse_bytes.push_back(id);
317 }
318 else
319 this->bytes.push_back(converter.get());
320 }
321
327};
328
333template <typename Component>
334 requires (has_dual_blink<Component>
335 && has_dual_pulse<Component>)
336struct midi_formater<Component> final
337 : dual_blinker<Component>
338 , dual_pulser<Component>
339{
340 using color_cnvrtr =
341 color_converter<typename Component::color_t>;
342
343 void set(uint8_t id, const color_cnvrtr& converter) override
344 {
345 if constexpr(is_sysex_out_component<Component>)
346 if (this->bytes.size() == sysex_formater<Component>
347 ::prefix_size())
348 this->bytes.push_back(Component::color_t::constant_id());
349
350 this->bytes.push_back(id);
351
352 switch (converter.get_state())
353 {
354 case color::blinking:
355 this->bytes.push_back(color_cnvrtr::clear_value);
356 this->blink_bytes.push_back(id);
357 this->blink_bytes.push_back(converter.get());
358 break;
359 case color::pulsing:
360 this->bytes.push_back(color_cnvrtr::clear_value);
361 this->pulse_bytes.push_back(id);
362 this->pulse_bytes.push_back(converter.get());
363 break;
364 default:
365 this->bytes.push_back(converter.get());
366 break;
367 }
368 }
369
376};
377
383template <typename Component>
384 requires (has_blink_offset<Component>
385 || has_pulse_offset<Component>)
386struct midi_formater<Component> final
387 : base_midi_formater<Component>
388{
389 using cmpnnt_clr = Component::color_t;
390
391 virtual void set(uint8_t id
392 , const color_converter<cmpnnt_clr>& converter)
393 {
394 this->bytes.push_back(id);
395 uint8_t value = converter.get();
396
397 switch (converter.get_state())
398 {
400 if constexpr (has_blink_offset<Component>)
401 value += cmpnnt_clr::blinking_offset();
402 else
403 value += cmpnnt_clr::pulsing_offset();
404 break;
406 if constexpr (has_pulse_offset<Component>)
407 value += cmpnnt_clr::pulsing_offset();
408 else
409 value += cmpnnt_clr::blinking_offset();
410 break;
411 default:
412 break;
413 }
414
415 this->bytes.push_back(value);
416 };
417};
418
419} // namespace buugi
Definition color.hpp:48
Definition midi_message.hpp:124
Definition midi_message.hpp:128
Definition midi_message.hpp:120
color::states get_state() const
Retrives the current state.
Definition color_converter.hpp:36
Value_t get() const
Retrives the main device specific colour value.
Definition color_converter.hpp:34
Provides underlying functionalities to format and store MIDI messages, before applying blinking or pu...
Definition midi_formater.hpp:28
bool has_message() const
Checks if a message is stored and ready to be sent to the device.
Definition midi_formater.hpp:65
virtual void set(uint8_t id, const color_converter< typename Component::color_t > &converter)
Converts and stores an LED's ID and color to the apropriate MIDI message.
Definition midi_formater.hpp:31
void add(uint8_t element)
Add a given value to a MIDI message. This method is intended to call specific commands on the device ...
Definition midi_formater.hpp:48
const libremidi::midi_bytes & get() const
Retrives the MIDI message currently stored.
Definition midi_formater.hpp:75
virtual void clear()
Removes all stores values of the message except for it's message type or prefix (NOTE_ON,...
Definition midi_formater.hpp:53
Povides convertion of color objects to device specific integer values.
Definition color_converter.hpp:57
@ blinking
Alternating between the colour and black.
Definition color.hpp:20
@ constant
Constant colour.
Definition color.hpp:19
@ pulsing
Smooth cycle between the colour and black.
Definition color.hpp:21
Enables the use of multiple buffers targetting diferent midi Channels. This method is used for device...
Definition midi_formater.hpp:117
const libremidi::midi_bytes & get_blink() const
Retrives the MIDI buffer dedicated to blinking LED's.
Definition midi_formater.hpp:137
void add_blink(uint8_t element)
Add a given value to a MIDI buffer dedicated to blinking LED's.
Definition midi_formater.hpp:132
void clear() override
Removes all stores values of the message except for it's message type or prefix (NOTE_ON,...
Definition midi_formater.hpp:166
bool has_blink_message() const
Checks if a message is stored in the buffer dedicated for bliking, and ready to be sent to the device...
Definition midi_formater.hpp:121
Enables the use of multiple buffers targetting diferent midi Channels. This method is used for device...
Definition midi_formater.hpp:226
void clear() override
Removes all stores values of the message except for it's message type or prefix (NOTE_ON,...
Definition midi_formater.hpp:275
const libremidi::midi_bytes & get_pulse() const
Retrives the MIDI buffer dedicated to pulsing LED's.
Definition midi_formater.hpp:246
bool has_pulse_message() const
Checks if a message is stored in the buffer dedicated for pulsing, and ready to be sent to the device...
Definition midi_formater.hpp:230
void add_pulse(uint8_t element)
Add a given value to a MIDI buffer dedicated to pulsing LED's.
Definition midi_formater.hpp:241
virtual void set(uint8_t id, const color_converter< cmpnnt_clr > &converter)
Converts and stores an LED's ID and color to the apropriate MIDI message.
Definition midi_formater.hpp:391
void clear() override
Removes all stores values of the message except for it's message type or prefix (NOTE_ON,...
Definition midi_formater.hpp:213
Empty enum for devices that do not feature anny blinking or pulsing functionalities.
Definition midi_formater.hpp:109
Provides funcitons to retrieve the prefix size for a specific componenet's SYSEX messages....
Definition midi_formater.hpp:16