Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
ble_midi_registry.hpp
Go to the documentation of this file.
1#pragma once
2
3// Process-wide registry that bridges a connected BLE-MIDI peripheral into the
4// platform MidiSystem's port list.
5//
6// Why this exists: on Apple, CoreMIDI itself exposes an OS-paired BLE
7// peripheral as a regular MIDI endpoint, so MidiSystem::enumerate_inputs()
8// shows it for free. Off Apple there is no such OS bridge — ALSA-seq does NOT
9// auto-create a port for a GATT notify stream. The BlueZ central therefore has
10// to publish the connection somewhere the platform MidiSystem can see it, and
11// the MidiSystem has to merge those published entries into its enumeration and
12// route open() on a BLE port id to the registry instead of the raw transport.
13//
14// This registry is the smallest honest seam for that: the central
15// register_input()/register_output() on connect (and unregister on
16// disconnect); the MidiSystem queries list_inputs()/list_outputs() to merge,
17// and attach_input_sink()/take_output_source() to wire delivery once a port is
18// opened. The registry owns NO transport — it only forwards bytes between the
19// central and the MidiInput/MidiOutput the host opened.
20//
21// All ids use the "ble-midi-in:<peripheral-id>" / "ble-midi-out:<peripheral-id>"
22// convention also produced by the Apple backend, so a host can pre-select a BLE
23// port via BleMidiCentral::midi_input_port_for() before it appears in
24// enumerate_inputs().
25//
26// Cross-platform + Skia-free: compiled on every platform so the central and the
27// MidiSystem link against one definition. On platforms whose central never
28// registers anything (the stub central) the registry simply stays empty and the
29// merge is a no-op.
30
31#include <pulp/midi/device.hpp>
32#include <pulp/midi/message.hpp>
33
34#include <functional>
35#include <string>
36#include <vector>
37
38namespace pulp::midi {
39
43class BleMidiPortRegistry {
44public:
45 static BleMidiPortRegistry& instance();
46
47 // ── Central side ────────────────────────────────────────────────────────
48
52 void register_input(const std::string& port_id, const std::string& name);
57 void register_output(const std::string& port_id, const std::string& name,
58 std::function<void(const std::vector<uint8_t>&)> sink);
59
62 void unregister_input(const std::string& port_id);
63 void unregister_output(const std::string& port_id);
64
68 void deliver_message(const std::string& port_id,
69 const std::vector<uint8_t>& bytes, double timestamp_sec);
70
71 // ── MidiSystem side ─────────────────────────────────────────────────────
72
75 std::vector<MidiPortInfo> list_inputs() const;
76 std::vector<MidiPortInfo> list_outputs() const;
77
81 bool is_input(const std::string& port_id) const;
82 bool is_output(const std::string& port_id) const;
83
88 bool attach_input(const std::string& port_id, MidiInputCallback callback,
89 MidiSysexCallback sysex_callback);
91 void detach_input(const std::string& port_id);
92
96 std::function<void(const std::vector<uint8_t>&)> output_sink(
97 const std::string& port_id) const;
98
99private:
100 BleMidiPortRegistry() = default;
101
102 struct Impl;
103 // Pimpl keeps <mutex>/<map> out of this widely-included header.
104 Impl& impl() const;
105};
106
107} // namespace pulp::midi
std::vector< MidiPortInfo > list_outputs() const
bool is_input(const std::string &port_id) const
True if port_id is a registered BLE input / output (so the platform MidiInput/MidiOutput knows to rou...
void unregister_output(const std::string &port_id)
bool attach_input(const std::string &port_id, MidiInputCallback callback, MidiSysexCallback sysex_callback)
Attach the host's MidiInput delivery callback to a BLE input port.
std::function< void(const std::vector< uint8_t > &)> output_sink(const std::string &port_id) const
Fetch a forwarding handle for a BLE output port so the host's MidiOutput can forward sent events.
void unregister_input(const std::string &port_id)
Remove a previously published port (on disconnect).
void detach_input(const std::string &port_id)
Detach the host's MidiInput delivery callback (on MidiInput::close()).
std::vector< MidiPortInfo > list_inputs() const
Currently-published BLE input / output ports, for the platform MidiSystem to merge into enumerate_inp...
static BleMidiPortRegistry & instance()
void register_output(const std::string &port_id, const std::string &name, std::function< void(const std::vector< uint8_t > &)> sink)
Publish a connected peripheral's output port ("ble-midi-out:<peripheral-id>").
bool is_output(const std::string &port_id) const
void deliver_message(const std::string &port_id, const std::vector< uint8_t > &bytes, double timestamp_sec)
Deliver a decoded MIDI message from the central to the host callback attached to port_id (if the host...
void register_input(const std::string &port_id, const std::string &name)
Publish a connected peripheral's input port.
Definition custom_node_events.hpp:26
std::function< void(const std::vector< uint8_t > &bytes, double timestamp_sec)> MidiSysexCallback
Definition device.hpp:22
std::function< void(const MidiEvent &event)> MidiInputCallback
Definition device.hpp:21