Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::midi::CiDiscovery Class Reference

MIDI-CI Discovery manager — handles CI message exchange. More...

#include <midi_ci.hpp>

Public Member Functions

 CiDiscovery ()
 RT-safe (constructs an MUID via std::mt19937; the random_device seed is one-shot at construction).
 ~CiDiscovery ()
 RT-safe.
void set_device_info (const CiDeviceInfo &info)
 RT-safe. Trivial copy of the small CiDeviceInfo struct.
const CiDeviceInfo & device_info () const
 RT-safe. Returns a reference; no allocation.
MUID local_muid () const
 RT-safe. Returns a 4-byte struct by value.
std::vector< uint8_t > process_message (const uint8_t *data, size_t size)
 NOT RT-safe — allocates a response vector and dispatches into handle_* methods that allocate.
std::vector< uint8_t > create_discovery_inquiry () const
 NOT RT-safe — allocates and returns a SysEx wire buffer.
std::vector< uint8_t > create_profile_inquiry (MUID destination) const
 NOT RT-safe — allocates and returns a SysEx wire buffer.
const std::vector< CiDeviceInfo > & discovered_devices () const
 RT-safe.
void add_profile (const ProfileState &profile)
 NOT RT-safe — std::vector::push_back may reallocate.
const std::vector< ProfileState > & profiles () const
 RT-safe. Returns a reference; no allocation.
bool enable_profile (const ProfileId &id)
 NOT RT-safe — invokes the on_profile_changed callback which may allocate.
bool disable_profile (const ProfileId &id)
 NOT RT-safe — see enable_profile.
void set_property (std::string_view resource, std::string_view value)
 NOT RT-safe — std::map::insert and string construction both allocate.
std::optional< std::string > get_property (std::string_view resource) const
 RT-safe with caveats: the lookup uses heterogeneous std::less<> so no string allocation occurs for the search key.
void add_function_block (const FunctionBlockInfo &block)
 NOT RT-safe — std::vector::push_back may reallocate.
const std::vector< FunctionBlockInfo > & function_blocks () const
 RT-safe. Returns a reference; no allocation.
const FunctionBlockInfo * find_function_block (FunctionBlockId id) const
 RT-safe.
std::vector< uint8_t > create_profile_added_report (MUID destination, const ProfileId &id)
 NOT RT-safe — allocates the wire bytes.
std::vector< uint8_t > create_profile_removed_report (MUID destination, const ProfileId &id)
 NOT RT-safe — allocates the wire bytes.
void set_profile_details (const ProfileId &id, uint8_t target, const std::vector< uint8_t > &data)
 NOT RT-safe — copies into a std::map; the value's std::vector<uint8_t> is also copied.
std::vector< ProfileDetails > profile_details_for (const ProfileId &id) const
 NOT RT-safe — allocates a result vector and copies stored data.
std::vector< uint8_t > create_profile_details_inquiry (MUID destination, const ProfileId &id, uint8_t target) const
 NOT RT-safe — allocates the wire bytes.
const std::vector< ProfileDetails > & discovered_profile_details () const
 RT-safe.
std::vector< uint8_t > create_profile_specific_data (MUID destination, const ProfileId &id, const uint8_t *data, std::size_t size) const
 NOT RT-safe — allocates the wire bytes.
std::vector< uint8_t > create_profile_specific_data (MUID destination, const ProfileId &id, const std::vector< uint8_t > &data) const
PeSubscriptionManager & subscription_manager ()
 NOT RT-safe — lazily allocates the underlying PeSubscriptionManager (heap allocation through std::make_unique).
const PeSubscriptionManager & subscription_manager () const
 NOT RT-safe — see non-const overload.
std::size_t notify (std::string_view resource, std::string_view header_json, const std::vector< uint8_t > &payload)
 NOT RT-safe — invokes subscription_manager() (potentially lazy allocation) and subscribers_of() (allocates a result vector), then invokes the on_pe_notify callback once per binding (callback body unknown to us).

Public Attributes

std::function< void(MUID source, const ProfileId &id, const std::vector< uint8_t > &data)> on_profile_specific_data
 Fires when a Profile-Specific Data message arrives.
std::function< void(const CiDeviceInfo &)> on_device_discovered
 Callbacks.
std::function< void(const ProfileId &, bool enabled)> on_profile_changed
std::function< void(MUID source, const ProfileId &)> on_profile_added
std::function< void(MUID source, const ProfileId &)> on_profile_removed
std::function< void(MUID source, const ProfileDetails &)> on_profile_details
PeNotifyCallback on_pe_notify
 Fires when a Subscribe peer should receive a Notify.

Detailed Description

MIDI-CI Discovery manager — handles CI message exchange.

RT-safety contract (audited 2026-05-26): every public method is annotated below. As a rule, CI is a UI/main thread surface (SysEx is slow, JSON parsing allocates, subscription state mutates). Call from the audio thread only methods explicitly tagged RT-safe.

Constructor & Destructor Documentation

◆ CiDiscovery()

pulp::midi::CiDiscovery::CiDiscovery ( )

RT-safe (constructs an MUID via std::mt19937; the random_device seed is one-shot at construction).

Construct from a non-RT thread.

◆ ~CiDiscovery()

pulp::midi::CiDiscovery::~CiDiscovery ( )

RT-safe.

Destructor frees the optional PeSubscriptionManager (heap free) — not RT-safe to call from the audio thread.

Member Function Documentation

◆ add_function_block()

void pulp::midi::CiDiscovery::add_function_block ( const FunctionBlockInfo & block)
inline

NOT RT-safe — std::vector::push_back may reallocate.

Call from the main / setup thread before the responder is exposed to peers.

◆ add_profile()

void pulp::midi::CiDiscovery::add_profile ( const ProfileState & profile)
inline

NOT RT-safe — std::vector::push_back may reallocate.

◆ create_discovery_inquiry()

std::vector< uint8_t > pulp::midi::CiDiscovery::create_discovery_inquiry ( ) const

NOT RT-safe — allocates and returns a SysEx wire buffer.

◆ create_profile_added_report()

std::vector< uint8_t > pulp::midi::CiDiscovery::create_profile_added_report ( MUID destination,
const ProfileId & id )

NOT RT-safe — allocates the wire bytes.

Send this from the responder when a profile becomes available so connected inquirers can update their cache without re-polling.

◆ create_profile_details_inquiry()

std::vector< uint8_t > pulp::midi::CiDiscovery::create_profile_details_inquiry ( MUID destination,
const ProfileId & id,
uint8_t target ) const

NOT RT-safe — allocates the wire bytes.

◆ create_profile_inquiry()

std::vector< uint8_t > pulp::midi::CiDiscovery::create_profile_inquiry ( MUID destination) const

NOT RT-safe — allocates and returns a SysEx wire buffer.

◆ create_profile_removed_report()

std::vector< uint8_t > pulp::midi::CiDiscovery::create_profile_removed_report ( MUID destination,
const ProfileId & id )

NOT RT-safe — allocates the wire bytes.

Mirror of the above for a profile that's just been removed.

◆ create_profile_specific_data() [1/2]

std::vector< uint8_t > pulp::midi::CiDiscovery::create_profile_specific_data ( MUID destination,
const ProfileId & id,
const std::vector< uint8_t > & data ) const
inline

◆ create_profile_specific_data() [2/2]

std::vector< uint8_t > pulp::midi::CiDiscovery::create_profile_specific_data ( MUID destination,
const ProfileId & id,
const uint8_t * data,
std::size_t size ) const

NOT RT-safe — allocates the wire bytes.

◆ device_info()

const CiDeviceInfo & pulp::midi::CiDiscovery::device_info ( ) const
inline

RT-safe. Returns a reference; no allocation.

◆ disable_profile()

bool pulp::midi::CiDiscovery::disable_profile ( const ProfileId & id)

NOT RT-safe — see enable_profile.

◆ discovered_devices()

const std::vector< CiDeviceInfo > & pulp::midi::CiDiscovery::discovered_devices ( ) const
inline

RT-safe.

Returns a reference to the internal vector; no allocation. The vector itself may grow on a non-RT thread via process_message(); readers should treat this as a snapshot, not a live view.

◆ discovered_profile_details()

const std::vector< ProfileDetails > & pulp::midi::CiDiscovery::discovered_profile_details ( ) const
inline

RT-safe.

Returns a reference; no allocation. The vector mutates on the dispatch thread; treat as a snapshot.

◆ enable_profile()

bool pulp::midi::CiDiscovery::enable_profile ( const ProfileId & id)

NOT RT-safe — invokes the on_profile_changed callback which may allocate.

The internal lookup is O(n) but allocation-free.

◆ find_function_block()

const FunctionBlockInfo * pulp::midi::CiDiscovery::find_function_block ( FunctionBlockId id) const
inline

RT-safe.

Linear scan over the function-block vector — small N (≤ 32 by spec).

◆ function_blocks()

const std::vector< FunctionBlockInfo > & pulp::midi::CiDiscovery::function_blocks ( ) const
inline

RT-safe. Returns a reference; no allocation.

◆ get_property()

std::optional< std::string > pulp::midi::CiDiscovery::get_property ( std::string_view resource) const

RT-safe with caveats: the lookup uses heterogeneous std::less<> so no string allocation occurs for the search key.

HOWEVER the return path constructs a std::string from the stored value, which allocates. Do not call from the audio thread. Use subscription_manager().subscribers_of() only on a non-RT thread.

◆ local_muid()

MUID pulp::midi::CiDiscovery::local_muid ( ) const
inline

RT-safe. Returns a 4-byte struct by value.

◆ notify()

std::size_t pulp::midi::CiDiscovery::notify ( std::string_view resource,
std::string_view header_json,
const std::vector< uint8_t > & payload )

NOT RT-safe — invokes subscription_manager() (potentially lazy allocation) and subscribers_of() (allocates a result vector), then invokes the on_pe_notify callback once per binding (callback body unknown to us).

Drive Notify from the same non-RT thread that produced the resource change.

◆ process_message()

std::vector< uint8_t > pulp::midi::CiDiscovery::process_message ( const uint8_t * data,
size_t size )

NOT RT-safe — allocates a response vector and dispatches into handle_* methods that allocate.

Call from the MIDI / main thread, never from the audio callback. Returns an empty vector when no reply is warranted.

◆ profile_details_for()

std::vector< ProfileDetails > pulp::midi::CiDiscovery::profile_details_for ( const ProfileId & id) const

NOT RT-safe — allocates a result vector and copies stored data.

◆ profiles()

const std::vector< ProfileState > & pulp::midi::CiDiscovery::profiles ( ) const
inline

RT-safe. Returns a reference; no allocation.

◆ set_device_info()

void pulp::midi::CiDiscovery::set_device_info ( const CiDeviceInfo & info)
inline

RT-safe. Trivial copy of the small CiDeviceInfo struct.

◆ set_profile_details()

void pulp::midi::CiDiscovery::set_profile_details ( const ProfileId & id,
uint8_t target,
const std::vector< uint8_t > & data )

NOT RT-safe — copies into a std::map; the value's std::vector<uint8_t> is also copied.

◆ set_property()

void pulp::midi::CiDiscovery::set_property ( std::string_view resource,
std::string_view value )

NOT RT-safe — std::map::insert and string construction both allocate.

Call from the main / property-mutation thread.

◆ subscription_manager() [1/2]

PeSubscriptionManager & pulp::midi::CiDiscovery::subscription_manager ( )

NOT RT-safe — lazily allocates the underlying PeSubscriptionManager (heap allocation through std::make_unique).

Construct or warm up the manager from the main thread before any RT thread observes it.

◆ subscription_manager() [2/2]

const PeSubscriptionManager & pulp::midi::CiDiscovery::subscription_manager ( ) const

NOT RT-safe — see non-const overload.

The const overload performs the same lazy allocation because sub_mgr_ is mutable.

Member Data Documentation

◆ on_device_discovered

std::function<void(const CiDeviceInfo&)> pulp::midi::CiDiscovery::on_device_discovered

Callbacks.

◆ on_pe_notify

PeNotifyCallback pulp::midi::CiDiscovery::on_pe_notify

Fires when a Subscribe peer should receive a Notify.

Set this to wire the manager's fan-out to the actual MIDI transport. Subscribe/Notify dispatcher.

The callback itself is invoked from notify() / handle_notify() and is therefore on the same thread as those calls — NOT the audio thread.

◆ on_profile_added

std::function<void(MUID source, const ProfileId&)> pulp::midi::CiDiscovery::on_profile_added

◆ on_profile_changed

std::function<void(const ProfileId&, bool enabled)> pulp::midi::CiDiscovery::on_profile_changed

◆ on_profile_details

std::function<void(MUID source, const ProfileDetails&)> pulp::midi::CiDiscovery::on_profile_details

◆ on_profile_removed

std::function<void(MUID source, const ProfileId&)> pulp::midi::CiDiscovery::on_profile_removed

◆ on_profile_specific_data

std::function<void(MUID source, const ProfileId& id, const std::vector<uint8_t>& data)> pulp::midi::CiDiscovery::on_profile_specific_data

Fires when a Profile-Specific Data message arrives.

The callback runs on the same thread that called process_message() — NOT the audio thread.


The documentation for this class was generated from the following file:
  • /home/runner/work/pulp/pulp/core/midi/include/pulp/midi/midi_ci.hpp