triggerbox: mostly functional slot swapping system
This commit is contained in:
parent
75699e384f
commit
bd873c6ba1
@ -235,6 +235,10 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
|
|||||||
double apparent_tempo() const { return _apparent_tempo; }
|
double apparent_tempo() const { return _apparent_tempo; }
|
||||||
double set_tempo (double t);
|
double set_tempo (double t);
|
||||||
|
|
||||||
|
void set_pending (Trigger*);
|
||||||
|
Trigger* swap_pending (Trigger*);
|
||||||
|
void swap_notify ();
|
||||||
|
|
||||||
virtual SegmentDescriptor get_segment_descriptor () const = 0;
|
virtual SegmentDescriptor get_segment_descriptor () const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -278,6 +282,8 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
|
|||||||
double _apparent_tempo;
|
double _apparent_tempo;
|
||||||
samplepos_t expected_end_sample;
|
samplepos_t expected_end_sample;
|
||||||
|
|
||||||
|
std::atomic<Trigger*> _pending;
|
||||||
|
|
||||||
void set_region_internal (boost::shared_ptr<Region>);
|
void set_region_internal (boost::shared_ptr<Region>);
|
||||||
virtual void retrigger() = 0;
|
virtual void retrigger() = 0;
|
||||||
virtual void set_usable_length () = 0;
|
virtual void set_usable_length () = 0;
|
||||||
@ -350,8 +356,6 @@ class LIBARDOUR_API AudioTrigger : public Trigger {
|
|||||||
samplecnt_t to_pad;
|
samplecnt_t to_pad;
|
||||||
samplecnt_t to_drop;
|
samplecnt_t to_drop;
|
||||||
|
|
||||||
PBD::RingBuffer<Data*> _deletion_queue;
|
|
||||||
|
|
||||||
void drop_data ();
|
void drop_data ();
|
||||||
int load_data (boost::shared_ptr<AudioRegion>);
|
int load_data (boost::shared_ptr<AudioRegion>);
|
||||||
void determine_tempo ();
|
void determine_tempo ();
|
||||||
@ -483,7 +487,7 @@ class LIBARDOUR_API TriggerBox : public Processor
|
|||||||
bool unbang_trigger (TriggerPtr);
|
bool unbang_trigger (TriggerPtr);
|
||||||
void add_trigger (TriggerPtr);
|
void add_trigger (TriggerPtr);
|
||||||
|
|
||||||
void set_pending (uint32_t slot, TriggerPtr);
|
void set_pending (uint32_t slot, Trigger*);
|
||||||
|
|
||||||
XMLNode& get_state (void);
|
XMLNode& get_state (void);
|
||||||
int set_state (const XMLNode&, int version);
|
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 request_reload (int32_t slot, void*);
|
||||||
void set_region (uint32_t slot, boost::shared_ptr<Region> region);
|
void set_region (uint32_t slot, boost::shared_ptr<Region> region);
|
||||||
|
|
||||||
|
PBD::Signal1<void,uint32_t> TriggerSwapped;
|
||||||
|
|
||||||
enum TriggerMidiMapMode {
|
enum TriggerMidiMapMode {
|
||||||
AbletonPush,
|
AbletonPush,
|
||||||
SequentialNote,
|
SequentialNote,
|
||||||
@ -557,7 +563,10 @@ class LIBARDOUR_API TriggerBox : public Processor
|
|||||||
int32_t _order;
|
int32_t _order;
|
||||||
Glib::Threads::RWLock trigger_lock; /* protects all_triggers */
|
Glib::Threads::RWLock trigger_lock; /* protects all_triggers */
|
||||||
Triggers all_triggers;
|
Triggers all_triggers;
|
||||||
Triggers pending;
|
|
||||||
|
typedef std::vector<Trigger*> PendingTriggers;
|
||||||
|
PendingTriggers pending;
|
||||||
|
|
||||||
PBD::RingBuffer<uint32_t> explicit_queue; /* user queued triggers */
|
PBD::RingBuffer<uint32_t> explicit_queue; /* user queued triggers */
|
||||||
TriggerPtr _currently_playing;
|
TriggerPtr _currently_playing;
|
||||||
Requests _requests;
|
Requests _requests;
|
||||||
@ -576,6 +585,8 @@ class LIBARDOUR_API TriggerBox : public Processor
|
|||||||
int determine_next_trigger (uint32_t n);
|
int determine_next_trigger (uint32_t n);
|
||||||
void stop_all ();
|
void stop_all ();
|
||||||
|
|
||||||
|
void maybe_swap_pending (uint32_t);
|
||||||
|
|
||||||
int note_to_trigger (int node, int channel);
|
int note_to_trigger (int node, int channel);
|
||||||
|
|
||||||
void note_on (int note_number, int velocity);
|
void note_on (int note_number, int velocity);
|
||||||
|
@ -91,6 +91,7 @@ Trigger::Trigger (uint32_t n, TriggerBox& b)
|
|||||||
, _barcnt (0.)
|
, _barcnt (0.)
|
||||||
, _apparent_tempo (0.)
|
, _apparent_tempo (0.)
|
||||||
, expected_end_sample (0)
|
, expected_end_sample (0)
|
||||||
|
, _pending ((Trigger*) 0)
|
||||||
{
|
{
|
||||||
add_property (_launch_style);
|
add_property (_launch_style);
|
||||||
add_property (_use_follow);
|
add_property (_use_follow);
|
||||||
@ -107,6 +108,28 @@ Trigger::Trigger (uint32_t n, TriggerBox& b)
|
|||||||
add_property (_isolated);
|
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
|
void
|
||||||
Trigger::set_use_follow (bool yn)
|
Trigger::set_use_follow (bool yn)
|
||||||
{
|
{
|
||||||
@ -276,7 +299,7 @@ Trigger::set_region (boost::shared_ptr<Region> r)
|
|||||||
{
|
{
|
||||||
if (!r) {
|
if (!r) {
|
||||||
/* clear operation, no need to talk to the worker thread */
|
/* clear operation, no need to talk to the worker thread */
|
||||||
_box.set_pending (_index, TriggerPtr());
|
set_pending ((Trigger*) 0);
|
||||||
} else {
|
} else {
|
||||||
/* load data, do analysis in another thread */
|
/* load data, do analysis in another thread */
|
||||||
TriggerBox::worker->set_region (_box, index(), r);
|
TriggerBox::worker->set_region (_box, index(), r);
|
||||||
@ -575,7 +598,6 @@ AudioTrigger::AudioTrigger (uint32_t n, TriggerBox& b)
|
|||||||
, got_stretcher_padding (false)
|
, got_stretcher_padding (false)
|
||||||
, to_pad (0)
|
, to_pad (0)
|
||||||
, to_drop (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));
|
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 */
|
/* This is called from our worker thread */
|
||||||
|
|
||||||
TriggerPtr t;
|
Trigger* t;
|
||||||
|
|
||||||
switch (_data_type) {
|
switch (_data_type) {
|
||||||
case DataType::AUDIO:
|
case DataType::AUDIO:
|
||||||
t = boost::make_shared<AudioTrigger> (slot, *this);
|
t = new AudioTrigger (slot, *this);
|
||||||
break;
|
break;
|
||||||
case DataType::MIDI:
|
case DataType::MIDI:
|
||||||
t = boost::make_shared<MIDITrigger> (slot, *this);
|
t = new MIDITrigger (slot, *this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1725,9 +1749,28 @@ TriggerBox::set_region (uint32_t slot, boost::shared_ptr<Region> region)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
void
|
||||||
@ -2118,6 +2161,12 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
|||||||
|
|
||||||
process_midi_trigger_requests (bufs);
|
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
|
/* STEP SIX: if at this point there is an active cue, make it trigger
|
||||||
* our corresponding slot
|
* 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) {
|
||||||
if ((_currently_playing = get_next_trigger()) != 0) {
|
if ((_currently_playing = get_next_trigger()) != 0) {
|
||||||
|
maybe_swap_pending (_currently_playing->index());
|
||||||
_currently_playing->startup ();
|
_currently_playing->startup ();
|
||||||
PropertyChanged (Properties::currently_playing);
|
PropertyChanged (Properties::currently_playing);
|
||||||
active_trigger_boxes.fetch_add (1);
|
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 */
|
explicit_queue.increment_read_idx (1); /* consume the entry we peeked at */
|
||||||
|
|
||||||
nxt->set_legato_offset (_currently_playing->current_pos());
|
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 ();
|
nxt->jump_start ();
|
||||||
_currently_playing->jump_stop ();
|
_currently_playing->jump_stop ();
|
||||||
/* and switch */
|
/* and switch */
|
||||||
@ -2236,6 +2292,11 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
|||||||
if (_currently_playing->state() == Trigger::Stopped) {
|
if (_currently_playing->state() == Trigger::Stopped) {
|
||||||
|
|
||||||
explicit_queue.increment_read_idx (1); /* consume the entry we peeked at */
|
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 ();
|
nxt->startup ();
|
||||||
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 was finished, started %2\n", _currently_playing->index(), nxt->index()));
|
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 was finished, started %2\n", _currently_playing->index(), nxt->index()));
|
||||||
_currently_playing = nxt;
|
_currently_playing = nxt;
|
||||||
|
Loading…
Reference in New Issue
Block a user