38#include <condition_variable>
45#include <unordered_map>
73constexpr const char*
kPrefix =
"audio_device_manager.";
74constexpr const char*
kOutputDevice =
"audio_device_manager.output_device";
75constexpr const char*
kInputDevice =
"audio_device_manager.input_device";
76constexpr const char*
kSampleRate =
"audio_device_manager.sample_rate";
77constexpr const char*
kBufferSize =
"audio_device_manager.buffer_size";
100 bool active() const noexcept {
return id_ != 0 && !manager_.expired(); }
109 uint64_t
id) noexcept
110 : manager_(
std::move(manager_ptr)), manager_raw_(manager_raw), id_(
id) {}
112 std::weak_ptr<void> manager_;
168 const std::vector<DeviceInfo>& available,
169 const std::string& fallback_output_id,
170 const std::string& fallback_input_id);
178 int default_output_channels = 2,
179 int default_input_channels = 0);
268 return id_ != 0 && !manager_.expired();
276 uint64_t
id) noexcept
277 : manager_(
std::move(manager_ptr)), manager_raw_(manager_raw), id_(
id) {}
279 std::weak_ptr<void> manager_;
309 std::function<void(
bool is_input,
const std::string& new_device_id)>;
320 const std::string& new_device_id);
404 bool install_port_change_callback =
true);
439 static std::vector<std::string>
444 const std::vector<std::string>& ids);
465 void unsubscribe_midi(uint64_t
id) noexcept;
466 void unsubscribe_device_change(uint64_t
id) noexcept;
467 void unsubscribe_midi_endpoint(uint64_t
id) noexcept;
468 void reconcile_midi_inputs();
481 std::shared_ptr<
void> lifetime_;
491 std::atomic<uint64_t> next_token_id_{1};
493 mutable std::mutex midi_mu_;
494 std::unordered_map<uint64_t, MidiHandler> midi_subs_;
496 mutable std::mutex device_change_mu_;
497 std::unordered_map<uint64_t, DeviceChangeHandler> device_change_subs_;
499 mutable std::mutex default_dev_mu_;
502 mutable std::mutex sr_mu_;
504 std::atomic<std::uint64_t> sr_change_count_{0};
505 std::atomic<double> last_sr_{0.0};
507 std::atomic<std::uint64_t> xrun_counter_{0};
509 mutable std::mutex midi_ep_mu_;
510 std::unordered_map<uint64_t, MidiEndpointChangeHandler> midi_ep_subs_;
511 std::vector<MidiEndpoint> midi_endpoints_;
512 bool endpoints_known_ =
false;
514 AudioSystem* attached_system_ =
nullptr;
520 struct EnabledInput {
522 std::unique_ptr<pulp::midi::MidiInput> device;
524 mutable std::mutex input_mu_;
525 std::vector<EnabledInput> enabled_inputs_;
526 pulp::midi::MidiSystem* midi_system_ =
nullptr;
527 std::shared_ptr<MidiPortLink> midi_link_;
532 std::recursive_mutex refresh_mu_;
533 bool midi_port_callback_installed_ =
false;
534 pulp::state::ApplicationProperties* settings_ =
nullptr;
536 AudioProcessLoadMeasurer load_;
541 std::atomic<bool> closed_{
false};
542 mutable std::mutex latch_mu_;
543 std::condition_variable latch_cv_;
RAII subscription token for device-change events.
Definition audio_device_manager.hpp:258
DeviceChangeToken & operator=(const DeviceChangeToken &)=delete
DeviceChangeToken(DeviceChangeToken &&other) noexcept
bool active() const noexcept
Definition audio_device_manager.hpp:267
friend class AudioDeviceManager
Definition audio_device_manager.hpp:273
DeviceChangeToken()=default
DeviceChangeToken & operator=(DeviceChangeToken &&other) noexcept
DeviceChangeToken(const DeviceChangeToken &)=delete
AudioDeviceManager — persistence + MIDI hub.
Definition audio_device_manager.hpp:132
void latch_close()
Latch the manager so subsequent dispatches are no-ops.
MidiSubscriptionToken subscribe_midi(MidiHandler handler)
Subscribe handler to incoming MIDI events.
std::size_t device_change_subscriber_count() const
Number of currently active device-change subscribers (tests).
bool is_closed() const noexcept
True after latch_close() has been called.
std::vector< std::string > enabled_midi_inputs() const
Identifiers of every enabled input, in the order they were enabled.
double last_sample_rate() const
Last known sample rate (set every dispatch_sample_rate_change).
std::function< void(const DeviceChangeEvent &)> DeviceChangeHandler
Definition audio_device_manager.hpp:253
static std::optional< DeviceSelection > load_selection(const pulp::state::ApplicationProperties &props)
Read persisted selection from props.user_settings().
void reset_peak_cpu_load()
Reset the peak tracker.
void bind_settings(pulp::state::ApplicationProperties *props)
Load the saved enabled set from props and write every later change to it.
void attach_midi_system(pulp::midi::MidiSystem *system, bool install_port_change_callback=true)
Bind the MIDI system the manager enumerates and opens inputs on.
MidiEndpointChangeKind
Definition audio_device_manager.hpp:362
friend class MidiSubscriptionToken
Definition audio_device_manager.hpp:462
static std::vector< std::string > load_enabled_midi_inputs(const pulp::state::ApplicationProperties &props)
Read the saved enabled-input identifiers.
std::function< void(double new_rate)> SampleRateChangeHandler
Subscribers learn when the active device's nominal sample rate changed.
Definition audio_device_manager.hpp:325
bool set_midi_input_enabled(const std::string &id, bool enabled)
Enable or disable a MIDI input by identifier.
void set_default_device_change_handler(DefaultDeviceChangeHandler handler)
Register a single default-device-change handler.
AudioDeviceManager & operator=(const AudioDeviceManager &)=delete
void set_midi_endpoints(std::vector< MidiEndpoint > endpoints)
Replace the manager's snapshot of live MIDI endpoints.
static DeviceConfig selection_to_config(const DeviceSelection &sel, int default_output_channels=2, int default_input_channels=0)
Convenience: convert a DeviceSelection to a DeviceConfig for AudioDevice::open().
void dispatch_default_device_change(bool is_input, const std::string &new_device_id)
Dispatch a default-device-change to the registered handler.
void dispatch_device_change(const DeviceChangeEvent &event)
Dispatch a device-change event to subscribers.
void bump_xrun_counter(std::uint64_t delta=1)
Increment the manager's internal xrun counter.
void end_cpu_measure()
End the current CPU-load window.
DeviceChangeKind
What kind of device-list mutation occurred.
Definition audio_device_manager.hpp:240
@ Unknown
List mutated; reason not disclosed.
Definition audio_device_manager.hpp:241
@ Removed
A device went away.
Definition audio_device_manager.hpp:243
@ Replaced
Bulk swap (e.g., USB hub reset).
Definition audio_device_manager.hpp:244
@ Added
A device became available.
Definition audio_device_manager.hpp:242
void reset_xrun_counter()
Reset the xrun counter to zero.
AudioDeviceManager(const AudioDeviceManager &)=delete
std::vector< MidiEndpoint > midi_endpoints() const
Current MIDI endpoint snapshot.
void set_sample_rate_change_handler(SampleRateChangeHandler handler)
std::size_t midi_subscriber_count() const
Number of currently registered subscribers.
MidiSubscriptionToken subscribe_midi_endpoints(MidiEndpointChangeHandler handler)
Subscribe to MIDI endpoint add/remove events.
static ResolveResult resolve_selection(const DeviceSelection &sel, const std::vector< DeviceInfo > &available, const std::string &fallback_output_id, const std::string &fallback_input_id)
std::function< void(bool is_input, const std::string &new_device_id)> DefaultDeviceChangeHandler
Subscribers learn when the system default output / input changed.
Definition audio_device_manager.hpp:308
std::uint64_t xrun_count() const
Snapshot the current xrun count. Safe from any thread.
float cpu_load() const
Smoothed CPU load in [0, +inf). 1.0 == full buffer.
bool is_midi_input_open(const std::string &id) const
True when id is enabled and currently open.
std::uint64_t sample_rate_change_count() const
Total number of sample-rate changes seen since construction.
void begin_cpu_measure(int num_frames, float sample_rate)
Begin a CPU-load measurement window.
std::function< void(const pulp::midi::MidiEvent &)> MidiHandler
Definition audio_device_manager.hpp:134
bool is_midi_input_enabled(const std::string &id) const
True when the user has enabled id, whether or not it is connected.
std::function< void(const MidiEndpointChange &)> MidiEndpointChangeHandler
Definition audio_device_manager.hpp:372
void attach_audio_system(AudioSystem *system)
Bind a live AudioSystem whose device-change callback should drive dispatch_device_change().
void refresh_midi_endpoints()
Re-enumerate the attached system, publish the result through set_midi_endpoints() and apply the reope...
DeviceChangeToken subscribe_device_changes(DeviceChangeHandler handler)
Subscribe to device-change events.
std::size_t midi_endpoint_subscriber_count() const
void dispatch_midi_event(const pulp::midi::MidiEvent &event)
Dispatch event to every active subscriber.
static bool save_selection(pulp::state::ApplicationProperties &props, const DeviceSelection &sel)
Write sel into props.user_settings() and save() the underlying file.
AudioProcessLoadSnapshot process_load_snapshot() const
Latest process-load telemetry.
void dispatch_sample_rate_change(double new_rate)
Dispatch a sample-rate-change event to the registered handler.
RuntimeTelemetrySnapshot runtime_telemetry_snapshot() const
static bool save_enabled_midi_inputs(pulp::state::ApplicationProperties &props, const std::vector< std::string > &ids)
Write the enabled-input identifiers; an empty list removes the key.
float peak_cpu_load() const
Peak CPU load since last reset_peak_cpu_load().
Definition device.hpp:149
MidiSubscriptionToken(const MidiSubscriptionToken &)=delete
MidiSubscriptionToken()=default
MidiSubscriptionToken & operator=(MidiSubscriptionToken &&other) noexcept
bool active() const noexcept
Definition audio_device_manager.hpp:100
MidiSubscriptionToken & operator=(const MidiSubscriptionToken &)=delete
void reset() noexcept
Reset and unsubscribe early.
friend class AudioDeviceManager
Definition audio_device_manager.hpp:106
MidiSubscriptionToken(MidiSubscriptionToken &&other) noexcept
Application-level properties with platform-standard paths.
Definition properties_file.hpp:72
Real-time CPU load measurement for audio callbacks.
Keys used under ApplicationProperties::user_settings().
Definition audio_device_manager.hpp:72
constexpr const char * kInputChannelMask
Definition audio_device_manager.hpp:79
constexpr const char * kEnabledMidiInputs
Newline-separated identifiers of the MIDI inputs the user enabled.
Definition audio_device_manager.hpp:82
constexpr const char * kSampleRate
Definition audio_device_manager.hpp:76
constexpr const char * kBufferSize
Definition audio_device_manager.hpp:77
constexpr const char * kOutputChannelMask
Definition audio_device_manager.hpp:78
constexpr const char * kOutputDevice
Definition audio_device_manager.hpp:74
constexpr const char * kInputDevice
Definition audio_device_manager.hpp:75
constexpr const char * kPrefix
Definition audio_device_manager.hpp:73
Definition analyzer_provider.hpp:12
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
Definition audio_device_manager.hpp:247
DeviceChangeKind kind
Definition audio_device_manager.hpp:248
std::string device_id
Affected id (when kind != Unknown).
Definition audio_device_manager.hpp:250
std::vector< DeviceInfo > devices
Snapshot at the time of the change.
Definition audio_device_manager.hpp:249
Definition audio_device_manager.hpp:367
MidiEndpointChangeKind kind
Definition audio_device_manager.hpp:368
MidiEndpoint endpoint
Definition audio_device_manager.hpp:369
Definition audio_device_manager.hpp:356
std::string name
Definition audio_device_manager.hpp:358
bool is_input
true == input; false == output.
Definition audio_device_manager.hpp:359
std::string id
Definition audio_device_manager.hpp:357
Resolve a stored selection against the live device list.
Definition audio_device_manager.hpp:161
bool fallback_used_input
Definition audio_device_manager.hpp:164
DeviceSelection resolved
Definition audio_device_manager.hpp:162
bool fallback_used_output
Definition audio_device_manager.hpp:163
Manager-owned runtime telemetry that combines callback load and backend xrun/overload counters for li...
Definition audio_device_manager.hpp:224
AudioProcessLoadSnapshot process_load
Definition audio_device_manager.hpp:225
std::uint64_t xrun_count
Definition audio_device_manager.hpp:226
Snapshot published by AudioProcessLoadMeasurer.
Definition load_measurer.hpp:25
Persisted audio-device selection.
Definition audio_device_manager.hpp:60
uint64_t output_channel_mask
Definition audio_device_manager.hpp:65
double sample_rate
0 = use default
Definition audio_device_manager.hpp:63
std::string input_device
Definition audio_device_manager.hpp:62
std::string output_device
Definition audio_device_manager.hpp:61
int buffer_size
0 = use default
Definition audio_device_manager.hpp:64
uint64_t input_channel_mask
Definition audio_device_manager.hpp:66
Timestamped MIDI event combining a choc::midi::ShortMessage with timing info.
Definition message.hpp:32