MayaFlux 0.4.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
33InputBinding InputBinding::hid_by_vid_pid(uint16_t vid, uint16_t pid)
34{
35 return {
37 .device_id = 0,
38 .hid_vendor_id = vid,
39 .hid_product_id = pid
40 };
41}
42
44 std::optional<uint8_t> cc_number,
45 std::optional<uint8_t> channel,
46 uint32_t device_id)
47{
48 return {
50 .device_id = device_id,
51 .midi_channel = channel,
52 .midi_message_type = 0xB0, // Control Change
53 .midi_cc_number = cc_number
54 };
55}
56
58 std::optional<uint8_t> channel,
59 uint32_t device_id)
60{
61 return {
63 .device_id = device_id,
64 .midi_channel = channel,
65 .midi_message_type = 0x90 // Note On
66 };
67}
68
70 std::optional<uint8_t> channel,
71 uint32_t device_id)
72{
73 return {
75 .device_id = device_id,
76 .midi_channel = channel,
77 .midi_message_type = 0x80 // Note Off
78 };
79}
80
82 std::optional<uint8_t> channel,
83 uint32_t device_id)
84{
85 return {
87 .device_id = device_id,
88 .midi_channel = channel,
89 .midi_message_type = 0xE0 // Pitch Bend
90 };
91}
92
98
100{
101 midi_cc_number = cc;
102 return *this;
103}
104
106{
107 osc_address_pattern = pattern;
108 return *this;
109}
110
111// ────────────────────────────────────────────────────────────────────────────
112// OSCMessage Argument Extraction Methods
113// ────────────────────────────────────────────────────────────────────────────
114
115std::optional<float> InputValue::OSCMessage::get_float(size_t index) const noexcept
116{
117 if (index >= arguments.size())
118 return std::nullopt;
119 return std::visit([](const auto& v) -> std::optional<float> {
120 using T = std::decay_t<decltype(v)>;
121 if constexpr (std::is_same_v<T, float>)
122 return v;
123 if constexpr (std::is_same_v<T, int32_t>)
124 return static_cast<float>(v);
125 return std::nullopt;
126 },
127 arguments[index]);
128}
129
130std::optional<int32_t> InputValue::OSCMessage::get_int(size_t index) const noexcept
131{
132 if (index >= arguments.size())
133 return std::nullopt;
134 return std::visit([](const auto& v) -> std::optional<int32_t> {
135 using T = std::decay_t<decltype(v)>;
136 if constexpr (std::is_same_v<T, int32_t>)
137 return v;
138 if constexpr (std::is_same_v<T, float>)
139 return static_cast<int32_t>(v);
140 return std::nullopt;
141 },
142 arguments[index]);
143}
144
145std::optional<std::string> InputValue::OSCMessage::get_string(size_t index) const noexcept
146{
147 if (index >= arguments.size())
148 return std::nullopt;
149 return std::visit([](const auto& v) -> std::optional<std::string> {
150 using T = std::decay_t<decltype(v)>;
151 if constexpr (std::is_same_v<T, std::string>)
152 return v;
153 return std::nullopt;
154 },
155 arguments[index]);
156}
157
158std::optional<std::vector<uint8_t>> InputValue::OSCMessage::get_blob(size_t index) const noexcept
159{
160 if (index >= arguments.size())
161 return std::nullopt;
162 return std::visit([](const auto& v) -> std::optional<std::vector<uint8_t>> {
163 using T = std::decay_t<decltype(v)>;
164 if constexpr (std::is_same_v<T, std::vector<uint8_t>>)
165 return v;
166 return std::nullopt;
167 },
168 arguments[index]);
169}
170
171// ────────────────────────────────────────────────────────────────────────────
172// InputDeviceInfo Implementation (inline)
173// ────────────────────────────────────────────────────────────────────────────
174
176{
177 return InputBinding {
179 .device_id = id
180 };
181}
182
184{
185 return InputBinding {
187 .device_id = id,
188 .midi_channel = channel
189 };
190}
191
192InputBinding InputDeviceInfo::to_binding_osc(const std::string& pattern) const
193{
194 return InputBinding {
196 .device_id = id,
197 .osc_address_pattern = pattern.empty() ? std::nullopt : std::optional(pattern)
198 };
199}
200
201InputValue InputValue::make_scalar(double v, uint32_t dev_id, InputType src)
202{
203 return {
205 .data = v,
206 .timestamp_ns = static_cast<uint64_t>(
207 std::chrono::steady_clock::now().time_since_epoch().count()),
208 .device_id = dev_id,
209 .source_type = src
210 };
211}
212
213InputValue InputValue::make_vector(std::vector<double> v, uint32_t dev_id, InputType src)
214{
215 return {
217 .data = std::move(v),
218 .timestamp_ns = static_cast<uint64_t>(
219 std::chrono::steady_clock::now().time_since_epoch().count()),
220 .device_id = dev_id,
221 .source_type = src
222 };
223}
224
225InputValue InputValue::make_bytes(std::vector<uint8_t> v, uint32_t dev_id, InputType src)
226{
227 return {
228 .type = Type::BYTES,
229 .data = std::move(v),
230 .timestamp_ns = static_cast<uint64_t>(
231 std::chrono::steady_clock::now().time_since_epoch().count()),
232 .device_id = dev_id,
233 .source_type = src
234 };
235}
236
237InputValue InputValue::make_midi(uint8_t status, uint8_t d1, uint8_t d2, uint32_t dev_id)
238{
239 return {
240 .type = Type::MIDI,
241 .data = MIDIMessage { .status = status, .data1 = d1, .data2 = d2 },
242 .timestamp_ns = static_cast<uint64_t>(
243 std::chrono::steady_clock::now().time_since_epoch().count()),
244 .device_id = dev_id,
246 };
247}
248
249InputValue InputValue::make_osc(std::string addr, std::vector<OSCArg> args, uint32_t dev_id)
250{
251 return {
252 .type = Type::OSC,
253 .data = OSCMessage { .address = std::move(addr), .arguments = std::move(args) },
254 .timestamp_ns = static_cast<uint64_t>(
255 std::chrono::steady_clock::now().time_since_epoch().count()),
256 .device_id = dev_id,
258 };
259}
260
261std::optional<double> InputValue::try_scalar() const noexcept
262{
263 if (type != Type::SCALAR)
264 return std::nullopt;
265 return std::get<double>(data);
266}
267
268const std::vector<double>* InputValue::try_vector() const noexcept
269{
270 if (type != Type::VECTOR)
271 return nullptr;
272 return &std::get<std::vector<double>>(data);
273}
274
275const std::vector<uint8_t>* InputValue::try_bytes() const noexcept
276{
277 if (type != Type::BYTES)
278 return nullptr;
279 return &std::get<std::vector<uint8_t>>(data);
280}
281
283{
284 if (type != Type::MIDI)
285 return nullptr;
286 return &std::get<MIDIMessage>(data);
287}
288
290{
291 if (type != Type::OSC)
292 return nullptr;
293 return &std::get<OSCMessage>(data);
294}
295
296} // namespace MayaFlux::Core
uint32_t channel
InputType
Input backend type enumeration.
@ OSC
Open Sound Control (network)
@ 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)
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.