13
0

modify and extend both Session and TriggerBox API to allow better transport control

This allows a stop transport request to first stop all active triggers and then stop the transport
This commit is contained in:
Paul Davis 2021-11-10 15:55:58 -07:00
parent 4b5fbeb455
commit 91a28b78c4
6 changed files with 57 additions and 10 deletions

View File

@ -485,7 +485,8 @@ public:
double default_play_speed ();
void reset_transport_speed (TransportRequestSource origin = TRS_UI);
void start_transport_from_processor ();
void start_transport_from_trigger ();
void stop_transport_from_trigger ();
void request_transport_speed (double speed, TransportRequestSource origin = TRS_UI);
void request_default_play_speed (double speed, TransportRequestSource origin = TRS_UI);
void request_transport_speed_nonzero (double, TransportRequestSource origin = TRS_UI);
@ -1430,6 +1431,7 @@ private:
bool _was_seamless;
bool _under_nsm_control;
unsigned int _xrun_count;
bool transport_started_by_trigger;
std::string _missing_file_replacement;

View File

@ -454,6 +454,8 @@ class LIBARDOUR_API TriggerBox : public Processor
static TriggerBoxThread* worker;
static void start_transport_stop (Session&);
private:
static Temporal::BBT_Offset _assumed_trigger_duration;
@ -530,7 +532,12 @@ class LIBARDOUR_API TriggerBox : public Processor
void reload (BufferSet& bufs, int32_t slot, void* ptr);
PBD::ScopedConnection stop_all_connection;
static void init_pool();
static std::atomic<int> active_trigger_boxes;
static PBD::Signal0<void> StopAllTriggers;
};
namespace Properties {

View File

@ -215,6 +215,7 @@ Session::Session (AudioEngine &eng,
, _writable (false)
, _under_nsm_control (false)
, _xrun_count (0)
, transport_started_by_trigger (false)
, master_wait_end (0)
, post_export_sync (false)
, post_export_position (0)

View File

@ -262,6 +262,7 @@ Session::process_routes (pframes_t nframes, bool& need_butler)
bool b = false;
if ((ret = (*i)->roll (nframes, start_sample, end_sample, b)) < 0) {
cerr << "ERR1 STOP\n";
TFSM_STOP (false, false);
return -1;
}
@ -953,7 +954,11 @@ Session::process_event (SessionEvent* ev)
break;
case SessionEvent::EndRoll:
TFSM_STOP (ev->yes_or_no, ev->second_yes_or_no);
if (transport_started_by_trigger) {
TriggerBox::start_transport_stop (*this);
} else {
TFSM_STOP (ev->yes_or_no, ev->second_yes_or_no);
}
break;
case SessionEvent::SetTransportMaster:
@ -988,6 +993,7 @@ Session::process_event (SessionEvent* ev)
break;
case SessionEvent::RangeStop:
cerr << "RANGE STOP\n";
TFSM_STOP (ev->yes_or_no, false);
remove = false;
del = false;
@ -1571,6 +1577,7 @@ Session::implement_master_strategy ()
TFSM_EVENT (TransportFSM::StartTransport);
break;
case TransportMasterStop:
cerr << "MASTER STOP\n";
TFSM_STOP (false, false);
break;
}

View File

@ -58,10 +58,11 @@
#include "ardour/profile.h"
#include "ardour/scene_changer.h"
#include "ardour/session.h"
#include "ardour/tempo.h"
#include "ardour/transport_fsm.h"
#include "ardour/transport_master.h"
#include "ardour/transport_master_manager.h"
#include "ardour/tempo.h"
#include "ardour/triggerbox.h"
#include "ardour/operations.h"
#include "ardour/vca.h"
#include "ardour/vca_manager.h"
@ -446,12 +447,21 @@ Session::stop_transport (bool abort, bool clear_state)
/** Called from the process thread */
void
Session::start_transport_from_processor ()
Session::start_transport_from_trigger ()
{
transport_started_by_trigger = true;
ENSURE_PROCESS_THREAD;
TFSM_ROLL();
}
/** Called from the process thread */
void
Session::stop_transport_from_trigger ()
{
ENSURE_PROCESS_THREAD;
TFSM_STOP (false, false);
}
/** Called from the process thread */
void
Session::start_transport (bool after_loop)

View File

@ -1379,7 +1379,9 @@ TriggerBox::TriggerMidiMapMode TriggerBox::_midi_map_mode (TriggerBox::Sequentia
int TriggerBox::_first_midi_note = 60;
std::atomic<int32_t> TriggerBox::_pending_scene (-1);
std::atomic<int32_t> TriggerBox::_active_scene (-1);
std::atomic<int> TriggerBox::active_trigger_boxes (0);
TriggerBoxThread* TriggerBox::worker = 0;
PBD::Signal0<void> TriggerBox::StopAllTriggers;
void
TriggerBox::init ()
@ -1389,6 +1391,16 @@ TriggerBox::init ()
init_pool ();
}
void
TriggerBox::start_transport_stop (Session& s)
{
if (active_trigger_boxes.load ()) {
StopAllTriggers(); /* EMIT SIGNAL */
} else {
s.stop_transport_from_trigger ();
}
}
TriggerBox::TriggerBox (Session& s, DataType dt)
: Processor (s, _("TriggerBox"), Temporal::BeatTime)
, _bang_queue (1024)
@ -1417,6 +1429,8 @@ TriggerBox::TriggerBox (Session& s, DataType dt)
Temporal::TempoMap::MapChanged.connect_same_thread (tempo_map_connection, boost::bind (&TriggerBox::tempo_map_change, this));
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));
}
void
@ -1592,6 +1606,8 @@ TriggerBox::stop_all ()
clear_implicit ();
explicit_queue.reset ();
_stop_all = false;
}
void
@ -1823,9 +1839,14 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
if (!currently_playing) {
if ((currently_playing = get_next_trigger ()) != 0) {
currently_playing->startup ();
active_trigger_boxes.fetch_add (1);
}
}
if (_stop_all) {
stop_all ();
}
if (!currently_playing) {
return;
}
@ -1833,7 +1854,7 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
/* transport must be active for triggers */
if (!_session.transport_state_rolling()) {
_session.start_transport_from_processor ();
_session.start_transport_from_trigger ();
}
timepos_t start (start_sample);
@ -1887,11 +1908,6 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
}
}
if (_stop_all) {
stop_all ();
_stop_all = false;
}
while (currently_playing) {
assert (currently_playing->state() >= Trigger::WaitingToStart);
@ -1999,6 +2015,10 @@ TriggerBox::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
} else {
currently_playing = 0;
if (active_trigger_boxes.fetch_sub (1) == 1) {
/* last active trigger box */
_session.stop_transport_from_trigger ();
}
}
} else {