diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index ae518ecf85..c85079616b 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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; diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 3564ab0184..a6a6489ba1 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -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 active_trigger_boxes; + static PBD::Signal0 StopAllTriggers; }; namespace Properties { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 3c7ff70c76..2936d6468a 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -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) diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 8a05943525..ce2bbcfc0e 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -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; } diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 2d5589856f..6516cda67b 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -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) diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index a71843b36c..349802e834 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -1379,7 +1379,9 @@ TriggerBox::TriggerMidiMapMode TriggerBox::_midi_map_mode (TriggerBox::Sequentia int TriggerBox::_first_midi_note = 60; std::atomic TriggerBox::_pending_scene (-1); std::atomic TriggerBox::_active_scene (-1); +std::atomic TriggerBox::active_trigger_boxes (0); TriggerBoxThread* TriggerBox::worker = 0; +PBD::Signal0 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 {