From 75699e384f6b89869e098badb4997764df49aaa9 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 21 Dec 2021 15:15:06 -0700 Subject: [PATCH] triggerbox: start of "pending" architecture to allow for thread-safe swapping of slot contents (Triggers) --- libs/ardour/ardour/triggerbox.h | 4 ++++ libs/ardour/triggerbox.cc | 41 +++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index b67157c4fd..fde62f6680 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -483,6 +483,8 @@ class LIBARDOUR_API TriggerBox : public Processor bool unbang_trigger (TriggerPtr); void add_trigger (TriggerPtr); + void set_pending (uint32_t slot, TriggerPtr); + XMLNode& get_state (void); int set_state (const XMLNode&, int version); @@ -511,6 +513,7 @@ class LIBARDOUR_API TriggerBox : public Processor void set_pass_thru (bool yn); void request_reload (int32_t slot, void*); + void set_region (uint32_t slot, boost::shared_ptr region); enum TriggerMidiMapMode { AbletonPush, @@ -554,6 +557,7 @@ class LIBARDOUR_API TriggerBox : public Processor int32_t _order; Glib::Threads::RWLock trigger_lock; /* protects all_triggers */ Triggers all_triggers; + Triggers pending; PBD::RingBuffer explicit_queue; /* user queued triggers */ TriggerPtr _currently_playing; Requests _requests; diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 7f842f5e2d..2d243229d4 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -274,7 +274,13 @@ Trigger::set_quantization (Temporal::BBT_Offset const & q) void Trigger::set_region (boost::shared_ptr r) { - TriggerBox::worker->set_region (_box, index(), r); + if (!r) { + /* clear operation, no need to talk to the worker thread */ + _box.set_pending (_index, TriggerPtr()); + } else { + /* load data, do analysis in another thread */ + TriggerBox::worker->set_region (_box, index(), r); + } } void @@ -1681,6 +1687,8 @@ TriggerBox::TriggerBox (Session& s, DataType dt) } } + pending.reserve (all_triggers.size()); + Config->ParameterChanged.connect_same_thread (*this, boost::bind (&TriggerBox::parameter_changed, this, _1)); StopAllTriggers.connect_same_thread (stop_all_connection, boost::bind (&TriggerBox::request_stop_all, this)); @@ -1693,6 +1701,35 @@ TriggerBox::scene_bang (uint32_t n) _pending_scene = n; } +void +TriggerBox::set_region (uint32_t slot, boost::shared_ptr region) +{ + /* This is called from our worker thread */ + + TriggerPtr t; + + switch (_data_type) { + case DataType::AUDIO: + t = boost::make_shared (slot, *this); + break; + case DataType::MIDI: + t = boost::make_shared (slot, *this); + break; + } + + t->set_region_threaded (region); + + /* XXX what happens if pending is already set? */ + + set_pending (slot, t); +} + +void +TriggerBox::set_pending (uint32_t slot, TriggerPtr t) +{ + pending[slot] = t; +} + void TriggerBox::scene_unbang (uint32_t n) { @@ -2700,7 +2737,7 @@ TriggerBoxThread::thread_work () while (requests.read (&req, 1) == 1) { switch (req->type) { case SetRegion: - req->box->trigger (req->slot)->set_region_threaded (req->region); + req->box->set_region (req->slot, req->region); break; default: break;