MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
InputBinding.cpp
Go to the documentation of this file.
1#include "InputBinding.hpp"
2
3namespace MayaFlux::Core {
4
5InputBinding InputBinding::hid(uint32_t device_id)
6{
7 return { .backend = InputType::HID, .device_id = device_id };
8}
9
10InputBinding InputBinding::midi(uint32_t device_id, std::optional<uint8_t> channel)
11{
12 return {
14 .device_id = device_id,
15 .midi_channel = channel
16 };
17}
18
19InputBinding InputBinding::osc(const std::string& pattern)
20{
21 return {
23 .device_id = 0,
24 .osc_address_pattern = pattern.empty() ? std::nullopt : std::optional(pattern)
25 };
26}
27
29{
30 return { .backend = InputType::SERIAL, .device_id = device_id };
31}
32
34{
35 return { .backend = InputType::TABLET, .device_id = device_id };
36}
37
38InputBinding InputBinding::hid_by_vid_pid(uint16_t vid, uint16_t pid)
39{
40 return {
42 .device_id = 0,
43 .hid_vendor_id = vid,
44 .hid_product_id = pid
45 };
46}
47
49 std::optional<uint8_t> cc_number,
50 std::optional<uint8_t> channel,
51 uint32_t device_id)
52{
53 return {
55 .device_id = device_id,
56 .midi_channel = channel,
57 .midi_message_type = 0xB0, // Control Change
58 .midi_cc_number = cc_number
59 };
60}
61
63 std::optional<uint8_t> channel,
64 uint32_t device_id)
65{
66 return {
68 .device_id = device_id,
69 .midi_channel = channel,
70 .midi_message_type = 0x90 // Note On
71 };
72}
73
75 std::optional<uint8_t> channel,
76 uint32_t device_id)
77{
78 return {
80 .device_id = device_id,
81 .midi_channel = channel,
82 .midi_message_type = 0x80 // Note Off
83 };
84}
85
87 std::optional<uint8_t> channel,
88 uint32_t device_id)
89{
90 return {
92 .device_id = device_id,
93 .midi_channel = channel,
94 .midi_message_type = 0xE0 // Pitch Bend
95 };
96}
97
99{
100 midi_channel = channel;
101 return *this;
102}
103
105{
106 midi_cc_number = cc;
107 return *this;
108}
109
111{
112 osc_address_pattern = pattern;
113 return *this;
114}
115
116// ────────────────────────────────────────────────────────────────────────────
117// OSCMessage Argument Extraction Methods
118// ────────────────────────────────────────────────────────────────────────────
119
120std::optional<float> InputValue::OSCMessage::get_float(size_t index) const noexcept
121{
122 if (index >= arguments.size())
123 return std::nullopt;
124 return std::visit([](const auto& v) -> std::optional<float> {
125 using T = std::decay_t<decltype(v)>;
126 if constexpr (std::is_same_v<T, float>)
127 return v;
128 if constexpr (std::is_same_v<T, int32_t>)
129 return static_cast<float>(v);
130 return std::nullopt;
131 },
132 arguments[index]);
133}
134
135std::optional<int32_t> InputValue::OSCMessage::get_int(size_t index) const noexcept
136{
137 if (index >= arguments.size())
138 return std::nullopt;
139 return std::visit([](const auto& v) -> std::optional<int32_t> {
140 using T = std::decay_t<decltype(v)>;
141 if constexpr (std::is_same_v<T, int32_t>)
142 return v;
143 if constexpr (std::is_same_v<T, float>)
144 return static_cast<int32_t>(v);
145 return std::nullopt;
146 },
147 arguments[index]);
148}
149
150std::optional<std::string> InputValue::OSCMessage::get_string(size_t index) const noexcept
151{
152 if (index >= arguments.size())
153 return std::nullopt;
154 return std::visit([](const auto& v) -> std::optional<std::string> {
155 using T = std::decay_t<decltype(v)>;
156 if constexpr (std::is_same_v<T, std::string>)
157 return v;
158 return std::nullopt;
159 },
160 arguments[index]);
161}
162
163std::optional<std::vector<uint8_t>> InputValue::OSCMessage::get_blob(size_t index) const noexcept
164{
165 if (index >= arguments.size())
166 return std::nullopt;
167 return std::visit([](const auto& v) -> std::optional<std::vector<uint8_t>> {
168 using T = std::decay_t<decltype(v)>;
169 if constexpr (std::is_same_v<T, std::vector<uint8_t>>)
170 return v;
171 return std::nullopt;
172 },
173 arguments[index]);
174}
175
176// ────────────────────────────────────────────────────────────────────────────
177// InputDeviceInfo Implementation (inline)
178// ────────────────────────────────────────────────────────────────────────────
179
181{
182 return InputBinding {
184 .device_id = id
185 };
186}
187
188InputBinding InputDeviceInfo::to_binding_midi(std::optional<uint8_t> channel) const
189{
190 return InputBinding {
192 .device_id = id,
193 .midi_channel = channel
194 };
195}
196
197InputBinding InputDeviceInfo::to_binding_osc(const std::string& pattern) const
198{
199 return InputBinding {
201 .device_id = id,
202 .osc_address_pattern = pattern.empty() ? std::nullopt : std::optional(pattern)
203 };
204}
205
206InputValue InputValue::make_scalar(double v, uint32_t dev_id, InputType src)
207{
208 return {
210 .data = v,
211 .timestamp_ns = static_cast<uint64_t>(
212 std::chrono::steady_clock::now().time_since_epoch().count()),
213 .device_id = dev_id,
214 .source_type = src
215 };
216}
217
218InputValue InputValue::make_vector(std::vector<double> v, uint32_t dev_id, InputType src)
219{
220 return {
222 .data = std::move(v),
223 .timestamp_ns = static_cast<uint64_t>(
224 std::chrono::steady_clock::now().time_since_epoch().count()),
225 .device_id = dev_id,
226 .source_type = src
227 };
228}
229
230InputValue InputValue::make_bytes(std::vector<uint8_t> v, uint32_t dev_id, InputType src)
231{
232 return {
233 .type = Type::BYTES,
234 .data = std::move(v),
235 .timestamp_ns = static_cast<uint64_t>(
236 std::chrono::steady_clock::now().time_since_epoch().count()),
237 .device_id = dev_id,
238 .source_type = src
239 };
240}
241
242InputValue InputValue::make_midi(uint8_t status, uint8_t d1, uint8_t d2, uint32_t dev_id)
243{
244 return {
245 .type = Type::MIDI,
246 .data = MIDIMessage { .status = status, .data1 = d1, .data2 = d2 },
247 .timestamp_ns = static_cast<uint64_t>(
248 std::chrono::steady_clock::now().time_since_epoch().count()),
249 .device_id = dev_id,
251 };
252}
253
254InputValue InputValue::make_osc(std::string addr, std::vector<OSCArg> args, uint32_t dev_id)
255{
256 return {
257 .type = Type::OSC,
258 .data = OSCMessage { .address = std::move(addr), .arguments = std::move(args) },
259 .timestamp_ns = static_cast<uint64_t>(
260 std::chrono::steady_clock::now().time_since_epoch().count()),
261 .device_id = dev_id,
263 };
264}
265
266std::optional<double> InputValue::try_scalar() const noexcept
267{
268 if (type != Type::SCALAR)
269 return std::nullopt;
270 return std::get<double>(data);
271}
272
273const std::vector<double>* InputValue::try_vector() const noexcept
274{
275 if (type != Type::VECTOR)
276 return nullptr;
277 return &std::get<std::vector<double>>(data);
278}
279
280const std::vector<uint8_t>* InputValue::try_bytes() const noexcept
281{
282 if (type != Type::BYTES)
283 return nullptr;
284 return &std::get<std::vector<uint8_t>>(data);
285}
286
288{
289 if (type != Type::MIDI)
290 return nullptr;
291 return &std::get<MIDIMessage>(data);
292}
293
295{
296 if (type != Type::OSC)
297 return nullptr;
298 return &std::get<OSCMessage>(data);
299}
300
301} // namespace MayaFlux::Core
uint32_t index
Definition VKDevice.cpp:142
InputType
Input backend type enumeration.
@ OSC
Open Sound Control (network)
@ TABLET
Digitizers and styluses (pressure, tilt, rotation)
@ HID
Generic HID devices (game controllers, custom hardware)
@ MIDI
MIDI controllers and instruments.
@ SERIAL
Serial port communication (Arduino, etc.)
static InputBinding hid_by_vid_pid(uint16_t vid, uint16_t pid)
Bind to HID device by vendor/product ID.
InputBinding & with_osc_pattern(const std::string &pattern)
Add OSC address pattern filter.
std::optional< uint8_t > midi_cc_number
Match specific CC number.
InputType backend
Which backend type.
static InputBinding midi_note_on(std::optional< uint8_t > channel={}, uint32_t device_id=0)
Bind to MIDI Note On messages.
static InputBinding midi_cc(std::optional< uint8_t > cc_number={}, std::optional< uint8_t > channel={}, uint32_t device_id=0)
Bind to MIDI Control Change messages.
static InputBinding midi(uint32_t device_id=0, std::optional< uint8_t > channel={})
Bind to MIDI device.
static InputBinding midi_pitch_bend(std::optional< uint8_t > channel={}, uint32_t device_id=0)
Bind to MIDI Pitch Bend messages.
std::optional< std::string > osc_address_pattern
Match OSC address prefix.
InputBinding & with_midi_channel(uint8_t channel)
Add MIDI channel filter.
std::optional< uint8_t > midi_channel
Match specific MIDI channel (1-16)
static InputBinding serial(uint32_t device_id=0)
Bind to Serial device.
static InputBinding midi_note_off(std::optional< uint8_t > channel={}, uint32_t device_id=0)
Bind to MIDI Note Off messages.
uint32_t device_id
Specific device (0 = any device)
static InputBinding tablet(uint32_t device_id=0)
Bind to a tablet tool.
InputBinding & with_midi_cc(uint8_t cc)
Add MIDI CC number filter.
static InputBinding osc(const std::string &pattern="")
Bind to OSC messages.
static InputBinding hid(uint32_t device_id=0)
Bind to HID device (any or specific)
Specifies what input an InputNode wants to receive.
InputBinding to_binding() const
Create a binding to this specific device.
uint32_t id
Unique device identifier within backend.
InputBinding to_binding_osc(const std::string &pattern) const
InputType backend_type
Which backend manages this device.
InputBinding to_binding_midi(std::optional< uint8_t > channel) const
Create a binding to this device with additional filters.
uint8_t status
Status byte (channel + message type)
std::optional< std::string > get_string(size_t index=0) const noexcept
Extract a string argument by index.
std::optional< std::vector< uint8_t > > get_blob(size_t index=0) const noexcept
Extract a blob argument by index.
std::optional< int32_t > get_int(size_t index=0) const noexcept
Extract an int32 argument by index.
std::string address
OSC address pattern.
std::optional< float > get_float(size_t index=0) const noexcept
Extract a float argument by index.
uint32_t device_id
Source device identifier.
static InputValue make_bytes(std::vector< uint8_t > v, uint32_t dev_id, InputType src)
static InputValue make_midi(uint8_t status, uint8_t d1, uint8_t d2, uint32_t dev_id)
std::optional< double > try_scalar() const noexcept
Safe scalar extraction.
const std::vector< double > * try_vector() const noexcept
Safe vector extraction.
@ OSC
Structured OSC message.
@ MIDI
Structured MIDI message.
@ VECTOR
Multiple float values (e.g., accelerometer xyz)
@ SCALAR
Single normalized float [-1.0, 1.0] or [0.0, 1.0].
@ BYTES
Raw byte data (HID reports, sysex)
static InputValue make_osc(std::string addr, std::vector< OSCArg > args, uint32_t dev_id)
std::variant< double, std::vector< double >, std::vector< uint8_t >, MIDIMessage, OSCMessage > data
InputType source_type
Backend that generated this value.
static InputValue make_scalar(double v, uint32_t dev_id, InputType src)
static InputValue make_vector(std::vector< double > v, uint32_t dev_id, InputType src)
const OSCMessage * try_osc() const noexcept
Safe OSC extraction.
const MIDIMessage * try_midi() const noexcept
Safe MIDI extraction.
const std::vector< uint8_t > * try_bytes() const noexcept
Safe bytes extraction.
Generic input value container.