BuGUI
BUtton Grid User Interface
Loading...
Searching...
No Matches
sysex_out.hpp
1#pragma once
2#include <hardware/component.hpp>
3#include <concepts/device.hpp>
4#include <concepts/message.hpp>
5#include <concepts/common.hpp>
6
7#include <libremidi/libremidi.hpp>
8
9namespace bugui
10{
11template <typename Device, typename Controller>
13 : virtual public component<Device, Controller>
14{
15 using grid_t = grid<Device, Controller>;
16 using buttons_t = buttons<Device, Controller>;
17
18 static constexpr auto prefix{Device::sysex_prefix()};
19 static constexpr auto p_size{prefix.size()};
20 static constexpr auto p_size_incr{p_size + 1};
21 libremidi::midi_bytes bytes{prefix.cbegin(), prefix.cend()};
22 libremidi::midi_bytes blink_bytes{bytes};
23 libremidi::midi_bytes pulse_bytes{bytes};
24
25 void send_color()
26 {
27 if (bytes.size() > p_size_incr)
28 send();
29 else
30 bytes.erase(bytes.begin() + p_size, bytes.end());
31
32 if (blink_bytes.size() > p_size_incr)
33 send_blink();
34 else
35 blink_bytes.erase(blink_bytes.begin() + p_size_incr
36 , blink_bytes.end());
37
38 if (pulse_bytes.size() > p_size_incr)
39 send_pulse();
40 else
41 pulse_bytes.erase(pulse_bytes.begin() + p_size_incr
42 , pulse_bytes.end());
43 }
44
45 void send()
46 {
47 bytes.push_back(Device::sysex_sufix());
48 m_output.send_message(bytes);
49 bytes.erase(bytes.begin() + p_size, bytes.end());
50 }
51
52 void send_blink()
53 {
54 blink_bytes.push_back(Device::sysex_sufix());
55 m_output.send_message(blink_bytes);
56 blink_bytes.erase(blink_bytes.begin() + p_size_incr
57 , blink_bytes.end());
58 }
59
60 void send_pulse()
61 {
62 pulse_bytes.push_back(Device::sysex_sufix());
63 m_output.send_message(pulse_bytes);
64 pulse_bytes.erase(pulse_bytes.begin() + p_size_incr
65 , pulse_bytes.end());
66 }
67
68protected:
69 ~sysex_out() override
70 {
71 clear();
72 m_output.close_port();
73 }
74
75 void init()
76 {
77 if (blink_bytes.size() == p_size)
78 blink_bytes.push_back(Device::blinking_color());
79 if (pulse_bytes.size() == p_size)
80 pulse_bytes.push_back(Device::pulsing_color());
81
82 if constexpr(has_init<Device>)
83 {
84 static constexpr auto init_m{Device::init()};
85 bytes.insert(bytes.end(), init_m.cbegin(), init_m.cend());
86 send();
87 }
88 }
89
90 void clear() override
91 {
92 if constexpr(has_clear<Device>)
93 {
94 static constexpr auto clear_m{Device::clear()};
95 bytes.insert(bytes.end(), clear_m.cbegin(), clear_m.cend());
96 }
97 else
98 {
99 if constexpr (has_color<Device>)
100 {
101 bytes.push_back(Device::constant_color());
102
103 if constexpr (has_grid<Device>)
104 grid_t::clear([this] (auto id)
105 {
106 this->bytese.push_back(id);
107 this->bytese.push_back(0); // OFF
108 });
109
110 if constexpr (has_buttons<Device>)
111 buttons_t::paint([this] (auto id)
112 {
113 bytes.push_back(id);
114 bytes.push_back(0); // OFF
115 });
116 }
117 }
118
119 send();
120 }
121
122 void set_grid(painter& p) override
123 {
124 if constexpr (has_color<Device> && has_grid<Device>)
125 {
126 bytes.push_back(Device::constant_color());
127
128 grid_t::paint(p, [this] (auto id, const auto& color)
129 {
130 bytes.push_back(id);
131
132 switch (color.get_state())
133 {
134 case color::blinking:
135 blink_bytes.push_back(id);
136 bytes.push_back(color.get_secondary());
137 blink_bytes.push_back(color.get());
138 break;
139 case color::pulsing:
140 pulse_bytes.push_back(id);
141 bytes.push_back(color.get_secondary());
142 pulse_bytes.push_back(color.get());
143 break;
144 default:
145 bytes.push_back(color.get());
146 break;
147 }
148 });
149
150 send_color();
151 }
152 }
153
154 void set_button(const button_painter& p) override
155 {
156 if constexpr (has_color<Device> && has_buttons<Device>)
157 {
158 bytes.push_back(Device::constant_color());
159
160 buttons_t::paint(p, [this] (auto id, const auto& color)
161 {
162 bytes.push_back(id);
163
164 switch (color.get_state())
165 {
166 case color::blinking:
167 blink_bytes.push_back(id);
168 bytes.push_back(color.get_secondary());
169 blink_bytes.push_back(color.get());
170 break;
171 case color::pulsing:
172 pulse_bytes.push_back(id);
173 bytes.push_back(color.get_secondary());
174 pulse_bytes.push_back(color.get());
175 break;
176 default:
177 bytes.push_back(color.get());
178 break;
179 }
180 });
181
182 send_color();
183 }
184 }
185
186 libremidi::midi_out m_output;
187};
188
189} // namespace bugui
Definition sysex_out.hpp:14
void set_grid(painter &p) override
Pass a reference to the painter object and display it's content to the grid.
Definition sysex_out.hpp:122
void clear() override
Turns off all LEDs.
Definition sysex_out.hpp:90
void set_button(const button_painter &p) override
Pass a reference to the button_painter object and display it's content to the device's buttons.
Definition sysex_out.hpp:154
Definition device.hpp:40
Definition device.hpp:54
Definition device.hpp:12
Definition device.hpp:31
Definition device.hpp:51
Conveys button colors from the controller to the base_hardware.
Definition button_painter.hpp:10
Empty struct for devices that do not feature labelled buttons.
Definition buttons.hpp:16
Generic colour class holding RGBA values of a primary and a secondary colour. The blinking and pulsin...
Definition color.hpp:12
states get_state() const noexcept
Retrieves the current state.
Definition color.hpp:61
rgba get_secondary() const noexcept
Retrieves the secondary colour as rgba values.
Definition color.hpp:58
@ blinking
Alternating between primary and secondary.
Definition color.hpp:18
@ pulsing
Smooth cycle between primary and secondary.
Definition color.hpp:19
rgba get() const noexcept
Retrieves the primary colour as rgba values.
Definition color.hpp:55
Inherits from all type of hardware components like grid, buttons... Provides the hardware type with t...
Definition component.hpp:14
Empty struct fro device's that do not feature a button grid.
Definition grid.hpp:18
The painter class.
Definition painter.hpp:12