13
0

triggerbox: mostly functional slot swapping system

This commit is contained in:
Paul Davis 2021-12-21 17:36:39 -07:00
parent 75699e384f
commit bd873c6ba1
2 changed files with 84 additions and 12 deletions

View File

@ -235,6 +235,10 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
double apparent_tempo() const { return _apparent_tempo; }
double set_tempo (double t);
void set_pending (Trigger*);
Trigger* swap_pending (Trigger*);
void swap_notify ();
virtual SegmentDescriptor get_segment_descriptor () const = 0;
protected:
@ -278,6 +282,8 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
double _apparent_tempo;
samplepos_t expected_end_sample;
std::atomic<Trigger*> _pending;
void set_region_internal (boost::shared_ptr<Region>);
virtual void retrigger() = 0;
virtual void set_usable_length () = 0;
@ -350,8 +356,6 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
samplecnt_t to_pad;
samplecnt_t to_drop;
PBD::RingBuffer<Data*> _deletion_queue;
void drop_data ();
int load_data (boost::shared_ptr<AudioRegion>);
void determine_tempo ();
@ -483,7 +487,7 @@ class LIBARDOUR_API TriggerBox : public Processor
bool unbang_trigger (TriggerPtr);
void add_trigger (TriggerPtr);
void set_pending (uint32_t slot, TriggerPtr);
void set_pending (uint32_t slot, Trigger*);
XMLNode& get_state (void);
int set_state (const XMLNode&, int version);
@ -515,6 +519,8 @@ class LIBARDOUR_API TriggerBox : public Processor
void request_reload (int32_t slot, void*);
void set_region (uint32_t slot, boost::shared_ptr<Region> region);
PBD::Signal1<void,uint32_t> TriggerSwapped;
enum TriggerMidiMapMode {
AbletonPush,
SequentialNote,
@ -557,7 +563,10 @@ class LIBARDOUR_API TriggerBox : public Processor
int32_t _order;
Glib::Threads::RWLock trigger_lock; /* protects all_triggers */
Triggers all_triggers;
Triggers pending;
typedef std::vector<Trigger*> PendingTriggers;
PendingTriggers pending;
PBD::RingBuffer<uint32_t> explicit_queue; /* user queued triggers */
TriggerPtr _currently_playing;
Requests _requests;
@ -576,6 +585,8 @@ class LIBARDOUR_API TriggerBox : public Processor
int determine_next_trigger (uint32_t n);
void stop_all ();
void maybe_swap_pending (uint32_t);
int note_to_trigger (int node, int channel);
void note_on (int note_number, int velocity);

View File

@ -91,6 +91,7 @@ Trigger::Trigger (uint32_t n, TriggerBox& b)
, _barcnt (0.)
, _apparent_tempo (0.)
, expected_end_sample (0)
, _pending ((Trigger*) 0)
{
add_property (_launch_style);
add_property (_use_follow);
@ -107,6 +108,28 @@ Trigger::Trigger (uint32_t n, TriggerBox& b)
add_property (_isolated);
}
void
Trigger::set_pending (Trigger* t)
{
Trigger* old = _pending.exchange (t);
if (old) {
/* new pending trigger set before existing pending trigger was used */
delete old;
}
}
void
Trigger::swap_notify ()
{
PropertyChanged (Properties::name);
}
Trigger*
Trigger::swap_pending (Trigger* t)
{
return _pending.exchange (t);
}
void
Trigger::set_use_follow (bool yn)
{
@ -276,7 +299,7 @@ Trigger::set_region (boost::shared_ptr<Region> r)
{
if (!r) {
/* clear operation, no need to talk to the worker thread */
_box.set_pending (_index, TriggerPtr());
set_pending ((Trigger*) 0);
} else {
/* load data, do analysis in another thread */
TriggerBox::worker->set_region (_box, index(), r);
@ -575,7 +598,6 @@ AudioTrigger::AudioTrigger (uint32_t n, TriggerBox& b)
, got_stretcher_padding (false)
, to_pad (0)
, to_drop (0)
, _deletion_queue (4)
{
}
@ -1687,7 +1709,9 @@ TriggerBox::TriggerBox (Session& s, DataType dt)
}
}
pending.reserve (all_triggers.size());
while (pending.size() < all_triggers.size()) {
pending.push_back (std::atomic<Trigger*>(0));
}
Config->ParameterChanged.connect_same_thread (*this, boost::bind (&TriggerBox::parameter_changed, this, _1));
@ -1706,14 +1730,14 @@ TriggerBox::set_region (uint32_t slot, boost::shared_ptr<Region> region)
{
/* This is called from our worker thread */
TriggerPtr t;
Trigger* t;
switch (_data_type) {
case DataType::AUDIO:
t = boost::make_shared<AudioTrigger> (slot, *this);
t = new AudioTrigger (slot, *this);
break;
case DataType::MIDI:
t = boost::make_shared<MIDITrigger> (slot, *this);
t = new MIDITrigger (slot, *this);
break;
}
@ -1725,9 +1749,28 @@ TriggerBox::set_region (uint32_t slot, boost::shared_ptr<Region> region)
}
void
TriggerBox::set_pending (uint32_t slot, TriggerPtr t)
TriggerBox::set_pending (uint32_t slot, Trigger* t)
{
pending[slot] = t;
all_triggers[slot]->set_pending (t);
}
void
TriggerBox::maybe_swap_pending (uint32_t slot)
{
Trigger* p = 0;
p = all_triggers[slot]->swap_pending (p);
if (p) {
std::cerr << " box " << order() << " slot " << slot << " pending discovered, switching\n";
if (all_triggers[slot]) {
// _deletion_queue....;
}
all_triggers[slot].reset (p);
TriggerSwapped (slot); /* EMIT SIGNAL */
}
}
void
@ -2118,6 +2161,12 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
process_midi_trigger_requests (bufs);
for (uint32_t n = 0; n < all_triggers.size(); ++n) {
if (all_triggers[n] != _currently_playing) {
maybe_swap_pending (n);
}
}
/* STEP SIX: if at this point there is an active cue, make it trigger
* our corresponding slot
*/
@ -2145,6 +2194,7 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
if (!_currently_playing) {
if ((_currently_playing = get_next_trigger()) != 0) {
maybe_swap_pending (_currently_playing->index());
_currently_playing->startup ();
PropertyChanged (Properties::currently_playing);
active_trigger_boxes.fetch_add (1);
@ -2222,6 +2272,12 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
explicit_queue.increment_read_idx (1); /* consume the entry we peeked at */
nxt->set_legato_offset (_currently_playing->current_pos());
/* starting up next trigger, check for pending */
maybe_swap_pending (n);
nxt = trigger (n);
nxt->jump_start ();
_currently_playing->jump_stop ();
/* and switch */
@ -2236,6 +2292,11 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
if (_currently_playing->state() == Trigger::Stopped) {
explicit_queue.increment_read_idx (1); /* consume the entry we peeked at */
/* starting up next trigger, check for pending */
maybe_swap_pending (n);
nxt = trigger (n);
nxt->startup ();
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 was finished, started %2\n", _currently_playing->index(), nxt->index()));
_currently_playing = nxt;