Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
osc.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4#include <vector>
5#include <variant>
6#include <cstdint>
7#include <functional>
8#include <memory>
9#include <string_view>
10#include <utility>
11
12namespace pulp::osc {
13
14// ── OSC Types ────────────────────────────────────────────────────────────────
15
18
19struct ColorRgba {
20 uint8_t r = 0;
21 uint8_t g = 0;
22 uint8_t b = 0;
23 uint8_t a = 0xff;
24
25 constexpr ColorRgba() = default;
26 constexpr ColorRgba(uint8_t r_, uint8_t g_, uint8_t b_, uint8_t a_ = 0xff)
27 : r(r_), g(g_), b(b_), a(a_) {}
28
29 bool operator==(const ColorRgba& o) const {
30 return r == o.r && g == o.g && b == o.b && a == o.a;
31 }
32};
33
34// OSC argument types (OSC 1.0 spec + the optional RGBA color type).
35using Argument = std::variant<int32_t, float, std::string,
36 std::vector<uint8_t>, ColorRgba>;
37
38// An OSC message: address pattern + typed arguments
39struct Message {
40 std::string address; // e.g., "/synth/freq"
41 std::vector<Argument> args;
42
43 // Convenience constructors
44 Message() = default;
45 explicit Message(std::string addr) : address(std::move(addr)) {}
46
47 Message& add(int32_t v) { args.emplace_back(v); return *this; }
48 Message& add(float v) { args.emplace_back(v); return *this; }
49 Message& add(std::string v) { args.emplace_back(std::move(v)); return *this; }
50 Message& add(std::vector<uint8_t> v) { args.emplace_back(std::move(v)); return *this; }
51 Message& add(ColorRgba c) { args.emplace_back(c); return *this; }
52
53 // Get argument at index (returns default if wrong type or out of range)
54 int32_t get_int(size_t i, int32_t def = 0) const;
55 float get_float(size_t i, float def = 0) const;
56 std::string get_string(size_t i, const std::string& def = "") const;
57 ColorRgba get_colour(size_t i, ColorRgba def = {}) const;
58};
59
60struct Bundle;
61
62// ── OSC Encoding/Decoding ────────────────────────────────────────────────────
63
64// Encode a message to OSC binary format
65std::vector<uint8_t> encode(const Message& msg);
66
67// Decode an OSC binary packet into a message
68// Returns an empty-address message if the data is malformed.
69Message decode(const uint8_t* data, size_t size);
70
71// ── OSC Sender ───────────────────────────────────────────────────────────────
72
73// Sends OSC messages over UDP
74class Sender {
75public:
78
79 // Connect to a target host:port
80 bool connect(const std::string& host, uint16_t port);
81
82 // Send a message
83 bool send(const Message& msg);
84
85 // Send a bundle
86 bool send(const Bundle& bundle);
87
88 // Send a raw, already-encoded OSC datagram (e.g., a #bundle or any
89 // byte-exact payload the caller has pre-built). Returns true if the
90 // full payload was sent.
91 bool send_raw(const uint8_t* data, size_t size);
92
93 // Disconnect
94 void disconnect();
95
96 bool is_connected() const;
97
98private:
99 struct Impl;
100 std::unique_ptr<Impl> impl_;
101};
102
103// ── OSC Receiver ─────────────────────────────────────────────────────────────
104
105// Receives OSC messages over UDP
106using MessageHandler = std::function<void(const Message&)>;
107using BundleHandler = std::function<void(const Bundle&)>;
108using FormatErrorHandler = std::function<void(std::string_view)>;
109
114
115// Address the receiver binds to. The receiver is IPv4-only, so this is a
116// dotted-quad literal. Loopback is the default: a Receiver is only reachable
117// from the local machine unless the caller binds all interfaces explicitly.
118inline constexpr std::string_view kBindLoopback = "127.0.0.1";
119inline constexpr std::string_view kBindAllInterfaces = "0.0.0.0";
120
125 std::vector<ReceiverRoute> routes;
126 // IPv4 literal to bind. Hostnames are not resolved; an unparseable value
127 // makes listen fail. Use kBindAllInterfaces to accept LAN controllers.
129};
130
131class Receiver {
132public:
135
136 Receiver(const Receiver&) = delete;
137 Receiver& operator=(const Receiver&) = delete;
138 Receiver(Receiver&&) = delete;
140
141 // Start listening on a port, bound to loopback (ReceiverOptions defaults).
142 bool listen(uint16_t port, MessageHandler handler);
143
144 // Start listening with bundle, error, and address-route callbacks.
145 // Receiver callbacks may call stop(); shutdown short-circuits remaining
146 // callbacks for the current datagram. Destroying a Receiver from its own
147 // callback is supported; worker state stays alive until the callback and
148 // receive thread finish unwinding.
149 bool listen_with_options(uint16_t port, ReceiverOptions options);
150
151 // Stop listening
152 void stop();
153
154 bool is_listening() const;
155 uint16_t local_port() const;
156 // Dotted-quad address the socket is bound to ("127.0.0.1", "0.0.0.0", ...);
157 // empty when not listening.
158 std::string local_address() const;
159
160 private:
161 void stop_impl(bool destroying);
162
163 struct Impl;
164 std::shared_ptr<Impl> impl_;
165};
166
167} // namespace pulp::osc
std::string local_address() const
bool listen(uint16_t port, MessageHandler handler)
Receiver(const Receiver &)=delete
Receiver & operator=(const Receiver &)=delete
bool is_listening() const
bool listen_with_options(uint16_t port, ReceiverOptions options)
Receiver(Receiver &&)=delete
Receiver & operator=(Receiver &&)=delete
uint16_t local_port() const
bool send_raw(const uint8_t *data, size_t size)
bool connect(const std::string &host, uint16_t port)
bool send(const Bundle &bundle)
bool send(const Message &msg)
bool is_connected() const
Bounded event contracts shared by host ingress and graph-authored nodes.
Definition anticipation_eligibility.hpp:9
Definition bundle.hpp:13
Message decode(const uint8_t *data, size_t size)
std::function< void(const Bundle &)> BundleHandler
Definition osc.hpp:107
constexpr std::string_view kBindLoopback
Definition osc.hpp:118
constexpr std::string_view kBindAllInterfaces
Definition osc.hpp:119
std::variant< int32_t, float, std::string, std::vector< uint8_t >, ColorRgba > Argument
Definition osc.hpp:35
std::function< void(std::string_view)> FormatErrorHandler
Definition osc.hpp:108
std::vector< uint8_t > encode(const Message &msg)
std::function< void(const Message &)> MessageHandler
Definition osc.hpp:106
STL namespace.
OSC Bundle — contains a timetag and a list of elements.
Definition bundle.hpp:60
32-bit RGBA color — the OSC 1.0 optional 'r' type tag.
Definition osc.hpp:19
uint8_t b
Definition osc.hpp:22
bool operator==(const ColorRgba &o) const
Definition osc.hpp:29
uint8_t g
Definition osc.hpp:21
uint8_t r
Definition osc.hpp:20
constexpr ColorRgba()=default
uint8_t a
Definition osc.hpp:23
constexpr ColorRgba(uint8_t r_, uint8_t g_, uint8_t b_, uint8_t a_=0xff)
Definition osc.hpp:26
Definition osc.hpp:39
float get_float(size_t i, float def=0) const
std::string get_string(size_t i, const std::string &def="") const
int32_t get_int(size_t i, int32_t def=0) const
Message(std::string addr)
Definition osc.hpp:45
Message & add(std::vector< uint8_t > v)
Definition osc.hpp:50
Message & add(ColorRgba c)
Definition osc.hpp:51
ColorRgba get_colour(size_t i, ColorRgba def={}) const
std::string address
Definition osc.hpp:40
std::vector< Argument > args
Definition osc.hpp:41
Message & add(std::string v)
Definition osc.hpp:49
Message & add(float v)
Definition osc.hpp:48
Message & add(int32_t v)
Definition osc.hpp:47
Definition osc.hpp:121
MessageHandler on_message
Definition osc.hpp:122
FormatErrorHandler on_error
Definition osc.hpp:124
std::string bind_address
Definition osc.hpp:128
std::vector< ReceiverRoute > routes
Definition osc.hpp:125
BundleHandler on_bundle
Definition osc.hpp:123
Definition osc.hpp:110
MessageHandler handler
Definition osc.hpp:112
std::string address_pattern
Definition osc.hpp:111