13
0

triggerbox: split apart semantics of WaitingToStop

This allows for a different quantization to be used when WaitingToSwitch,
used when we explicitly start a different Trigger. When "just stopping"
we continue to use 1 bar quantization; when switching to a different
Trigger we use the quantization of the next Trigger
This commit is contained in:
Paul Davis 2022-02-20 09:20:47 -07:00
parent 61b728bdcc
commit b9de15d285
3 changed files with 40 additions and 4 deletions

View File

@ -69,6 +69,10 @@ typedef uint32_t color_t;
LIBARDOUR_API std::string cue_marker_name (int32_t);
class Trigger;
typedef boost::shared_ptr<Trigger> TriggerPtr;
class LIBARDOUR_API Trigger : public PBD::Stateful {
public:
enum State {
@ -97,6 +101,12 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
* transition to Stopping and then Stopped.
*/
WaitingToStop,
/* a Trigger in this state is delivering data during calls to ::run(), but
* is waiting for the next occurence of another Trigger's quantization to occur when it will
* transition to Stopping and then Stopped (and be followed by
* the other Trigger.
*/
WaitingToSwitch,
/* a Trigger in this state was Running but noticed that it should stop
* during the current call to ::run(). By the end of that call, it will
* have transitioned to Stopped.
@ -323,6 +333,7 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
virtual void jump_start ();
virtual void jump_stop (BufferSet& bufs, pframes_t dest_offset);
void begin_stop (bool explicit_stop = false);
void begin_switch (TriggerPtr);
bool explicitly_stopped() const { return _explicitly_stopped; }
@ -409,6 +420,7 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
samplepos_t expected_end_sample;
Temporal::BBT_Offset _start_quantization;
Temporal::BBT_Offset _nxt_quantization;
std::atomic<Trigger*> _pending;
std::atomic<unsigned int> last_property_generation;
@ -421,8 +433,6 @@ class LIBARDOUR_API Trigger : public PBD::Stateful {
void send_property_change (PBD::PropertyChange pc);
};
typedef boost::shared_ptr<Trigger> TriggerPtr;
class LIBARDOUR_API AudioTrigger : public Trigger {
public:
AudioTrigger (uint32_t index, TriggerBox&);

View File

@ -855,6 +855,7 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Trigger, Running);
REGISTER_CLASS_ENUM (Trigger, WaitingForRetrigger);
REGISTER_CLASS_ENUM (Trigger, WaitingToStop);
REGISTER_CLASS_ENUM (Trigger, WaitingToSwitch);
REGISTER_CLASS_ENUM (Trigger, Stopping);
REGISTER (_TriggerState);

View File

@ -695,6 +695,18 @@ Trigger::begin_stop (bool explicit_stop)
send_property_change (ARDOUR::Properties::running);
}
void
Trigger::begin_switch (TriggerPtr nxt)
{
/* this is used when we start a tell a currently playing trigger to
stop, but wait for quantization first.
*/
_state = WaitingToSwitch;
_nxt_quantization = nxt->_quantization;
DEBUG_TRACE (DEBUG::Triggers, string_compose ("%1 begin_switch() requested state %2\n", index(), enum_2_string (_state)));
send_property_change (ARDOUR::Properties::running);
}
void
Trigger::process_state_requests (BufferSet& bufs, pframes_t dest_offset)
{
@ -759,6 +771,7 @@ Trigger::process_state_requests (BufferSet& bufs, pframes_t dest_offset)
case WaitingToStart:
case WaitingToStop:
case WaitingToSwitch:
case WaitingForRetrigger:
case Stopping:
break;
@ -780,6 +793,7 @@ Trigger::process_state_requests (BufferSet& bufs, pframes_t dest_offset)
case Stopped:
case Stopping: /* theoretically not possible */
case WaitingToStop:
case WaitingToSwitch:
case WaitingForRetrigger:
/* do nothing */
break;
@ -872,7 +886,13 @@ Trigger::compute_next_transition (samplepos_t start_sample, Temporal::Beats cons
/* Clips don't stop on their own quantize; in Live they stop on the Global Quantize setting; we will choose 1 bar (Live's default) for now */
#warning when Global Quantize is implemented, use that instead of '1 bar' here
if (_state == WaitingToStop) {
q = BBT_Offset(1,0,0);
} else if (_state == WaitingToSwitch) {
q = _nxt_quantization;
}
if (!compute_quantized_transition (start_sample, start, end, t_bbt, t_beats, t_samples, tmap, q)) {
@ -882,6 +902,7 @@ Trigger::compute_next_transition (samplepos_t start_sample, Temporal::Beats cons
switch (_state) {
case WaitingToStop:
case WaitingToSwitch:
nframes = t_samples - start_sample;
break;
@ -934,6 +955,7 @@ Trigger::maybe_compute_next_transition (samplepos_t start_sample, Temporal::Beat
switch (_state) {
case WaitingToStop:
case WaitingToSwitch:
_state = Stopping;
send_property_change (ARDOUR::Properties::running);
@ -1684,6 +1706,7 @@ AudioTrigger::audio_run (BufferSet& bufs, samplepos_t start_sample, samplepos_t
return nframes;
case Running:
case WaitingToStop:
case WaitingToSwitch:
case Stopping:
/* stuff to do */
break;
@ -2405,6 +2428,7 @@ MIDITrigger::midi_run (BufferSet& bufs, samplepos_t start_sample, samplepos_t en
return nframes;
case Running:
case WaitingToStop:
case WaitingToSwitch:
case Stopping:
break;
}
@ -3644,7 +3668,7 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
_currently_playing = nxt;
PropertyChanged (Properties::currently_playing);
} else if (_currently_playing->state() != Trigger::WaitingToStop) {
} else if (_currently_playing->state() != Trigger::WaitingToSwitch) {
/* Notice that this condition
* leaves the next trigger to
@ -3652,10 +3676,11 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
*/
/* but just begin stoppingthe currently playing slot */
_currently_playing->begin_stop ();
_currently_playing->begin_switch (nxt);
DEBUG_TRACE (DEBUG::Triggers, string_compose ("start stop for %1 before switching to %2\n", _currently_playing->index(), nxt->index()));
}
}
}
}