Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
ump_virtual_endpoint.hpp
Go to the documentation of this file.
1#pragma once
2
3// VirtualUmpEndpoint — purely in-process UMP endpoint.
4//
5// A `VirtualUmpEndpoint` is a `UmpEndpoint` with no OS handle: packets sent into it are
6// queued and re-delivered to the registered receive callback
7// synchronously inside `send()`. This is the workhorse for
8// headless tests (the CoreMIDI side rejects connections without a
9// real graphics session) and for in-process loopback between a
10// plugin's internal Generator and Sink (think: a built-in test
11// signal arpeggiator wired straight into the synth).
12//
13// Thread model:
14// - `send()` is callable from any thread. It runs the receive
15// callback on the calling thread, immediately, with no locking
16// beyond a single std::mutex around the callback pointer swap.
17// - `set_receive_callback()` may be called from any thread; it
18// swaps under the same mutex so a concurrent `send()` either
19// sees the old or the new callback (never half-installed).
20//
21// Lifetime:
22// - The endpoint is registered with a `UmpSession`; the session
23// owns it. Destroying the session destroys all virtual
24// endpoints. Callers can also retain a `std::shared_ptr<VirtualUmpEndpoint>`
25// handle they got from `register_virtual_endpoint` for direct
26// `send()` access.
27//
28// Loopback variant:
29// - For round-trip tests, set `loopback = true`. Packets sent
30// into the endpoint are also re-emitted to the callback.
31// (Default false to keep the unidirectional case behaving
32// like a real physical sink.)
33
35
36#include <atomic>
37#include <mutex>
38#include <string>
39
40namespace pulp::midi {
41
45 std::string name = "Pulp Virtual UMP";
50 bool loopback = false;
55};
56
58public:
60
61 const UmpEndpointInfo& info() const noexcept override { return info_; }
62
64
68 bool send(const UmpPacket& packet) override;
69
70 bool is_open() const noexcept override { return open_.load(std::memory_order_acquire); }
71
76 bool deliver(const UmpPacket& packet, double timestamp_sec = 0.0);
77
80 std::uint64_t sent_count() const noexcept { return sent_.load(std::memory_order_relaxed); }
81 std::uint64_t delivered_count() const noexcept { return delivered_.load(std::memory_order_relaxed); }
82
86 void close();
87
88private:
89 UmpEndpointInfo info_;
90 bool loopback_;
91
92 mutable std::mutex cb_mu_;
94
95 std::atomic<bool> open_{true};
96 std::atomic<std::uint64_t> sent_{0};
97 std::atomic<std::uint64_t> delivered_{0};
98};
99
100} // namespace pulp::midi
Polymorphic endpoint handle.
Definition ump_endpoint.hpp:69
void set_receive_callback(UmpReceiveCallback cb) override
Register the receive callback.
void close()
Tear-down hook — marks is_open() false and detaches the callback.
bool is_open() const noexcept override
True iff the endpoint is currently usable (port connected, virtual endpoint live).
Definition ump_virtual_endpoint.hpp:70
bool send(const UmpPacket &packet) override
send() writes a packet "out" of this endpoint.
bool deliver(const UmpPacket &packet, double timestamp_sec=0.0)
Deliver a packet directly to the receive callback as if it arrived from elsewhere.
const UmpEndpointInfo & info() const noexcept override
Snapshot of the endpoint's static metadata.
Definition ump_virtual_endpoint.hpp:61
std::uint64_t sent_count() const noexcept
Atomic counters useful for tests; never load-bearing for the real backend (CoreMIDI counters live els...
Definition ump_virtual_endpoint.hpp:80
std::uint64_t delivered_count() const noexcept
Definition ump_virtual_endpoint.hpp:81
VirtualUmpEndpoint(VirtualUmpEndpointConfig cfg)
Definition custom_node_events.hpp:26
std::function< void(const UmpPacket &packet, double timestamp_sec)> UmpReceiveCallback
Receive callback.
Definition ump_endpoint.hpp:64
Direction the endpoint exposes.
Definition ump_endpoint.hpp:40
Static description of an endpoint discovered on the system or registered virtually.
Definition ump_endpoint.hpp:47
Definition ump.hpp:84
Configuration for a newly-registered virtual endpoint.
Definition ump_virtual_endpoint.hpp:44
bool loopback
True if send() should also fire the receive callback (round-trip loopback).
Definition ump_virtual_endpoint.hpp:50
std::string name
Definition ump_virtual_endpoint.hpp:45
UmpEndpointDirection direction
Direction the endpoint advertises in its info().
Definition ump_virtual_endpoint.hpp:54