15#include <condition_variable>
28 std::vector<MidiPortInfo>
added;
37 return a.id == b.id && a.name == b.name && a.is_input == b.is_input &&
38 a.is_output == b.is_output;
41 for (
const auto& q : list) {
55 const std::vector<MidiPortInfo>& after) {
57 std::vector<bool> matched(after.size(),
false);
58 for (
const auto& b : before) {
60 for (std::size_t i = 0; i < after.size(); ++i) {
68 d.removed.push_back(b);
70 for (std::size_t i = 0; i < after.size(); ++i) {
72 d.added.push_back(after[i]);
86 last_ = std::move(current);
87 have_baseline_ =
true;
92 std::vector<MidiPortInfo> last_;
93 bool have_baseline_ =
false;
103 using Enumerate = std::function<std::vector<MidiPortInfo>()>;
117 std::chrono::milliseconds interval = std::chrono::milliseconds(1000)) {
120 if (worker_.joinable() && worker_.get_id() == std::this_thread::get_id())
125 auto state = std::make_shared<State>();
126 state->tracker.update(enumerate());
128 worker_ = std::thread(
129 [
state, enumerate = std::move(enumerate), on_change = std::move(on_change), interval] {
130 std::unique_lock<std::mutex> lk(
state->mu);
131 while (!
state->stopping) {
132 state->cv.wait_for(lk, interval, [&
state] {
return state->stopping; });
136 const auto diff =
state->tracker.update(enumerate());
137 if (!diff.empty() && on_change)
145 if (
auto state = state_) {
147 std::lock_guard<std::mutex> lk(
state->mu);
148 state->stopping =
true;
150 state->cv.notify_all();
154 if (worker_.joinable() && worker_.get_id() != std::this_thread::get_id())
159 return worker_.joinable();
165 std::condition_variable cv;
166 bool stopping =
false;
170 std::shared_ptr<State> state_;
PortChangePoller()=default
std::function< std::vector< MidiPortInfo >()> Enumerate
Definition port_change_watcher.hpp:103
void start(Enumerate enumerate, OnChange on_change, std::chrono::milliseconds interval=std::chrono::milliseconds(1000))
Start polling.
Definition port_change_watcher.hpp:116
bool running() const
Definition port_change_watcher.hpp:158
PortChangePoller & operator=(const PortChangePoller &)=delete
void stop()
Definition port_change_watcher.hpp:144
PortChangePoller(const PortChangePoller &)=delete
~PortChangePoller()
Definition port_change_watcher.hpp:109
std::function< void(const PortListDiff &)> OnChange
Definition port_change_watcher.hpp:104
Remembers the last snapshot and reports what changed since.
Definition port_change_watcher.hpp:78
PortListDiff update(std::vector< MidiPortInfo > current)
Record current and return the difference from the previous snapshot.
Definition port_change_watcher.hpp:82
Definition port_change_watcher.hpp:35
bool contains_port(const std::vector< MidiPortInfo > &list, const MidiPortInfo &p)
Definition port_change_watcher.hpp:40
bool same_port(const MidiPortInfo &a, const MidiPortInfo &b)
Definition port_change_watcher.hpp:36
Definition custom_node_events.hpp:26
PortListDiff diff_port_lists(const std::vector< MidiPortInfo > &before, const std::vector< MidiPortInfo > &after)
Compare two snapshots.
Definition port_change_watcher.hpp:54
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
Ports that appeared and ports that went away between two snapshots.
Definition port_change_watcher.hpp:27
std::vector< MidiPortInfo > added
Definition port_change_watcher.hpp:28
bool empty() const
Definition port_change_watcher.hpp:30
std::vector< MidiPortInfo > removed
Definition port_change_watcher.hpp:29