13
0

triggerbox: start of "pending" architecture to allow for thread-safe swapping of slot contents (Triggers)

This commit is contained in:
Paul Davis 2021-12-21 15:15:06 -07:00
parent c18d175f55
commit 75699e384f
2 changed files with 43 additions and 2 deletions

View File

@ -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> 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<uint32_t> explicit_queue; /* user queued triggers */
TriggerPtr _currently_playing;
Requests _requests;

View File

@ -274,7 +274,13 @@ Trigger::set_quantization (Temporal::BBT_Offset const & q)
void
Trigger::set_region (boost::shared_ptr<Region> 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> region)
{
/* This is called from our worker thread */
TriggerPtr t;
switch (_data_type) {
case DataType::AUDIO:
t = boost::make_shared<AudioTrigger> (slot, *this);
break;
case DataType::MIDI:
t = boost::make_shared<MIDITrigger> (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;