MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
InputBinding.hpp
Go to the documentation of this file.
1#pragma once
2
3namespace MayaFlux::Core {
4
5/**
6 * @brief Input backend type enumeration
7 */
8enum class InputType : uint8_t {
9 HID, ///< Generic HID devices (game controllers, custom hardware)
10 MIDI, ///< MIDI controllers and instruments
11 OSC, ///< Open Sound Control (network)
12 SERIAL, ///< Serial port communication (Arduino, etc.)
13 CUSTOM ///< User-defined input backends
14};
15
16// ────────────────────────────────────────────────────────────────────────────
17// Input Binding (Subscription Filter)
18// ────────────────────────────────────────────────────────────────────────────
19
20/**
21 * @struct InputBinding
22 * @brief Specifies what input an InputNode wants to receive
23 *
24 * Used when registering nodes to filter which input events they receive.
25 * Can match by backend type, specific device, or additional filters like
26 * MIDI channel or OSC address pattern.
27 */
28struct MAYAFLUX_API InputBinding {
29 InputType backend; ///< Which backend type
30 uint32_t device_id { 0 }; ///< Specific device (0 = any device)
31
32 std::optional<uint8_t> midi_channel; ///< Match specific MIDI channel (1-16)
33 std::optional<uint8_t> midi_message_type; ///< Match message type (0xB0=CC, 0x90=NoteOn, etc.)
34 std::optional<uint8_t> midi_cc_number; ///< Match specific CC number
35
36 std::optional<std::string> osc_address_pattern; ///< Match OSC address prefix
37
38 std::optional<uint16_t> hid_vendor_id; ///< Match HID vendor ID
39 std::optional<uint16_t> hid_product_id; ///< Match HID product ID
40
41 // ────────────────────────────────────────────────────────────────────────
42 // Factory Methods: Simple Bindings
43 // ────────────────────────────────────────────────────────────────────────
44
45 /**
46 * @brief Bind to HID device (any or specific)
47 * @param device_id Device ID (0 = any HID device)
48 */
49 static InputBinding hid(uint32_t device_id = 0);
50
51 /**
52 * @brief Bind to MIDI device
53 * @param device_id Device ID (0 = any MIDI device)
54 * @param channel MIDI channel filter (1-16, nullopt = any)
55 */
56 static InputBinding midi(uint32_t device_id = 0, std::optional<uint8_t> channel = {});
57
58 /**
59 * @brief Bind to OSC messages
60 * @param pattern OSC address pattern to match (empty = all)
61 */
62 static InputBinding osc(const std::string& pattern = "");
63
64 /**
65 * @brief Bind to Serial device
66 * @param device_id Device ID (0 = any Serial device)
67 */
68 static InputBinding serial(uint32_t device_id = 0);
69
70 // ────────────────────────────────────────────────────────────────────────
71 // Factory Methods: Advanced HID Bindings
72 // ────────────────────────────────────────────────────────────────────────
73
74 /**
75 * @brief Bind to HID device by vendor/product ID
76 * @param vid USB Vendor ID
77 * @param pid USB Product ID
78 *
79 * Matches any device with this VID/PID, regardless of enumeration order.
80 * Useful for binding to specific controller models.
81 */
82 static InputBinding hid_by_vid_pid(uint16_t vid, uint16_t pid);
83
84 // ────────────────────────────────────────────────────────────────────────
85 // Factory Methods: Advanced MIDI Bindings
86 // ────────────────────────────────────────────────────────────────────────
87
88 /**
89 * @brief Bind to MIDI Control Change messages
90 * @param cc_number CC number (0-127, nullopt = any CC)
91 * @param channel MIDI channel (1-16, nullopt = any channel)
92 * @param device_id Device ID (0 = any device)
93 */
94 static InputBinding midi_cc(
95 std::optional<uint8_t> cc_number = {},
96 std::optional<uint8_t> channel = {},
97 uint32_t device_id = 0);
98
99 /**
100 * @brief Bind to MIDI Note On messages
101 * @param channel MIDI channel (1-16, nullopt = any channel)
102 * @param device_id Device ID (0 = any device)
103 */
104 static InputBinding midi_note_on(
105 std::optional<uint8_t> channel = {},
106 uint32_t device_id = 0);
107
108 /**
109 * @brief Bind to MIDI Note Off messages
110 * @param channel MIDI channel (1-16, nullopt = any channel)
111 * @param device_id Device ID (0 = any device)
112 */
113 static InputBinding midi_note_off(
114 std::optional<uint8_t> channel = {},
115 uint32_t device_id = 0);
116
117 /**
118 * @brief Bind to MIDI Pitch Bend messages
119 * @param channel MIDI channel (1-16, nullopt = any channel)
120 * @param device_id Device ID (0 = any device)
121 */
122 static InputBinding midi_pitch_bend(
123 std::optional<uint8_t> channel = {},
124 uint32_t device_id = 0);
125
126 // ────────────────────────────────────────────────────────────────────────
127 // Chaining Methods (Builder Pattern)
128 // ────────────────────────────────────────────────────────────────────────
129
130 /**
131 * @brief Add MIDI channel filter
132 */
133 InputBinding& with_midi_channel(uint8_t channel);
134
135 /**
136 * @brief Add MIDI CC number filter
137 */
138 InputBinding& with_midi_cc(uint8_t cc);
139
140 /**
141 * @brief Add OSC address pattern filter
142 */
143 InputBinding& with_osc_pattern(const std::string& pattern);
144};
145
146// ────────────────────────────────────────────────────────────────────────────
147// Input Device Information
148// ────────────────────────────────────────────────────────────────────────────
149
150/**
151 * @struct InputDeviceInfo
152 * @brief Information about a connected input device
153 *
154 * Returned by device enumeration. Contains both universal fields
155 * and backend-specific fields (only populated when relevant).
156 */
157struct MAYAFLUX_API InputDeviceInfo {
158 // ─── Universal Fields ───
159 uint32_t id; ///< Unique device identifier within backend
160 std::string name; ///< Human-readable device name
161 std::string manufacturer; ///< Device manufacturer (if available)
162 InputType backend_type; ///< Which backend manages this device
163 bool is_connected; ///< Current connection state
164
165 // ─── HID-Specific ───
166 uint16_t vendor_id {}; ///< USB Vendor ID
167 uint16_t product_id {}; ///< USB Product ID
168 std::string serial_number; ///< Device serial (if available)
169
170 // ─── MIDI-Specific ───
171 bool is_input {}; ///< Can receive MIDI
172 bool is_output {}; ///< Can send MIDI
173 uint8_t port_number {}; ///< MIDI port index
174
175 // ─── OSC-Specific ───
176 std::string address; ///< IP address or hostname
177 uint16_t port {}; ///< UDP/TCP port
178
179 // ─── Serial-Specific ───
180 std::string port_name; ///< e.g., "/dev/ttyUSB0" or "COM3"
181 uint32_t baud_rate {}; ///< Serial baud rate
182
183 // ────────────────────────────────────────────────────────────────────────
184 // Convenience: Create InputBinding from this device
185 // ────────────────────────────────────────────────────────────────────────
186
187 /**
188 * @brief Create a binding to this specific device
189 * @return InputBinding configured for this device
190 */
191 [[nodiscard]] InputBinding to_binding() const;
192
193 /**
194 * @brief Create a binding to this device with additional filters
195 */
196 [[nodiscard]] InputBinding to_binding_midi(std::optional<uint8_t> channel) const;
197 [[nodiscard]] InputBinding to_binding_osc(const std::string& pattern) const;
198};
199
200/**
201 * @brief Generic input value container
202 *
203 * Represents a single input event from any backend type.
204 * Uses variant to handle different data formats efficiently.
205 */
206struct MAYAFLUX_API InputValue {
207 /**
208 * @brief Type of input data
209 */
210 enum class Type : uint8_t {
211 SCALAR, ///< Single normalized float [-1.0, 1.0] or [0.0, 1.0]
212 VECTOR, ///< Multiple float values (e.g., accelerometer xyz)
213 BYTES, ///< Raw byte data (HID reports, sysex)
214 MIDI, ///< Structured MIDI message
215 OSC ///< Structured OSC message
216 };
217
218 /**
219 * @brief MIDI message structure
220 */
221 struct MIDIMessage {
222 uint8_t status; ///< Status byte (channel + message type)
223 uint8_t data1; ///< First data byte
224 uint8_t data2; ///< Second data byte (may be unused)
225 [[nodiscard]] uint8_t channel() const { return status & 0x0F; }
226 [[nodiscard]] uint8_t type() const { return status & 0xF0; }
227 };
228
229 /**
230 * @brief OSC argument types
231 */
232 using OSCArg = std::variant<int32_t, float, std::string, std::vector<uint8_t>>;
233
234 /**
235 * @brief OSC message structure
236 */
237 struct OSCMessage {
238 std::string address; ///< OSC address pattern
239 std::vector<OSCArg> arguments; ///< Typed arguments
240 };
241
243 std::variant<
244 double, ///< SCALAR
245 std::vector<double>, ///< VECTOR
246 std::vector<uint8_t>, ///< BYTES
247 MIDIMessage, ///< MIDI
248 OSCMessage ///< OSC
249 >
251
252 uint64_t timestamp_ns; ///< Nanoseconds since epoch (or backend start)
253 uint32_t device_id; ///< Source device identifier
254 InputType source_type; ///< Backend that generated this value
255
256 [[nodiscard]] double as_scalar() const { return std::get<double>(data); }
257 [[nodiscard]] const std::vector<double>& as_vector() const { return std::get<std::vector<double>>(data); }
258 [[nodiscard]] const std::vector<uint8_t>& as_bytes() const { return std::get<std::vector<uint8_t>>(data); }
259 [[nodiscard]] const MIDIMessage& as_midi() const { return std::get<MIDIMessage>(data); }
260 [[nodiscard]] const OSCMessage& as_osc() const { return std::get<OSCMessage>(data); }
261
262 static InputValue make_scalar(double v, uint32_t dev_id, InputType src);
263
264 static InputValue make_vector(std::vector<double> v, uint32_t dev_id, InputType src);
265
266 static InputValue make_bytes(std::vector<uint8_t> v, uint32_t dev_id, InputType src);
267
268 static InputValue make_midi(uint8_t status, uint8_t d1, uint8_t d2, uint32_t dev_id);
269
270 static InputValue make_osc(std::string addr, std::vector<OSCArg> args, uint32_t dev_id);
271};
272
273} // namespace MayaFlux::Core
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.)
std::optional< uint8_t > midi_cc_number
Match specific CC number.
InputType backend
Which backend type.
std::optional< std::string > osc_address_pattern
Match OSC address prefix.
std::optional< uint16_t > hid_vendor_id
Match HID vendor ID.
std::optional< uint8_t > midi_channel
Match specific MIDI channel (1-16)
std::optional< uint8_t > midi_message_type
Match message type (0xB0=CC, 0x90=NoteOn, etc.)
std::optional< uint16_t > hid_product_id
Match HID product ID.
Specifies what input an InputNode wants to receive.
std::string address
IP address or hostname.
bool is_connected
Current connection state.
std::string name
Human-readable device name.
std::string manufacturer
Device manufacturer (if available)
uint32_t id
Unique device identifier within backend.
std::string serial_number
Device serial (if available)
InputType backend_type
Which backend manages this device.
std::string port_name
e.g., "/dev/ttyUSB0" or "COM3"
Information about a connected input device.
uint8_t status
Status byte (channel + message type)
uint8_t data2
Second data byte (may be unused)
std::vector< OSCArg > arguments
Typed arguments.
std::string address
OSC address pattern.
uint32_t device_id
Source device identifier.
const std::vector< uint8_t > & as_bytes() const
const std::vector< double > & as_vector() const
uint64_t timestamp_ns
Nanoseconds since epoch (or backend start)
const OSCMessage & as_osc() const
std::variant< double, std::vector< double >, std::vector< uint8_t >, MIDIMessage, OSCMessage > data
std::variant< int32_t, float, std::string, std::vector< uint8_t > > OSCArg
OSC argument types.
InputType source_type
Backend that generated this value.
const MIDIMessage & as_midi() const
Generic input value container.