From 8b4e71400695acd1dad3598965e92455272c0562 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 5 Dec 2019 13:00:24 -0700 Subject: changes to use overwrite-buffers when loop is disabled or loop range changed --- libs/ardour/ardour/session.h | 4 +- libs/ardour/session.cc | 23 ++++--- libs/ardour/session_butler.cc | 7 +- libs/ardour/session_process.cc | 6 +- libs/ardour/session_transport.cc | 141 ++++++++++++++++++--------------------- 5 files changed, 89 insertions(+), 92 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 3a3f16dfdf..6c34a1b93f 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1683,8 +1683,8 @@ private: bool should_ignore_transport_request (TransportRequestSource, TransportRequestType) const; - void set_play_loop (bool yn); - void unset_play_loop (); + void set_play_loop (bool yn, bool change_transport_state); + void unset_play_loop (bool change_transport_state = false); void overwrite_some_buffers (boost::shared_ptr); void flush_all_inserts (); int micro_locate (samplecnt_t distance); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index d5579eb6fc..7e107b3056 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1425,28 +1425,29 @@ Session::auto_loop_changed (Location* location) (*i)->reload_loop (); } + if (rolling) { if (play_loop) { + /* Set this so that when/if we have to stop the + * transport for a locate, we know that it is triggered + * by loop-changing, and we do not cancel play loop + */ + + loop_changing = true; + if (_transport_sample < location->start() || _transport_sample > location->end()) { // new loop range excludes current transport // sample => relocate to beginning of loop and roll. - request_locate (location->start(), true); - } else if (!loop_changing) { + request_locate (location->start(), true); - // schedule a locate-roll to refill the diskstreams at the - // previous loop end + } - loop_changing = true; + // schedule a buffer overwrite to refill buffers with the new loop. - if (location->end() > last_loopend) { - clear_events (SessionEvent::LocateRoll); - SessionEvent *ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, last_loopend, last_loopend, 0, true); - queue_event (ev); - } - } + request_overwrite_buffer (boost::shared_ptr()); } } else { diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index b36d5459f3..0e9aa128dd 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -89,10 +89,15 @@ Session::request_overwrite_buffer (boost::shared_ptr t) queue_event (ev); } -/** Process thread. */ void Session::overwrite_some_buffers (boost::shared_ptr r) { + /* this is called from the process thread while handling queued + * SessionEvents. Therefore neither playback sample or read offsets in + * tracks will change while we "queue" them all for an upcoming + * overwrite. + */ + if (actively_recording()) { return; } diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 020deb41e9..a7e8a068af 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -852,7 +852,7 @@ Session::process_event (SessionEvent* ev) switch (ev->type) { case SessionEvent::SetLoop: - set_play_loop (ev->yes_or_no); + set_play_loop (ev->yes_or_no, true); break; case SessionEvent::AutoLoop: @@ -937,6 +937,10 @@ Session::process_event (SessionEvent* ev) overwrite_some_buffers (ev->track); break; + case SessionEvent::OverwriteAll: + overwrite_some_buffers (boost::shared_ptr()); + break; + case SessionEvent::Audition: set_audition (ev->region); // drop reference to region diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 6d9f99127a..6fd3114be6 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -302,7 +302,7 @@ Session::locate (samplepos_t target_sample, bool with_roll, bool with_flush, boo have_looped = false; if (!Config->get_loop_is_mode()) { - set_play_loop (false); + set_play_loop (false, false); } else { /* this will make the non_realtime_locate() in the butler which then causes seek() in tracks actually do the right @@ -808,63 +808,10 @@ Session::flush_all_inserts () } } -void -Session::set_play_loop (bool yn) -{ - ENSURE_PROCESS_THREAD; - /* Called from event-handling context */ - - DEBUG_TRACE (DEBUG::Transport, string_compose ("set_play_loop (%1)\n", yn)); - - Location *loc; - - if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) { - /* nothing to do, or can't change loop status while recording */ - return; - } - - if (yn && synced_to_engine()) { - warning << string_compose ( - _("Looping cannot be supported while %1 is using JACK transport.\n" - "Recommend changing the configured options"), PROGRAM_NAME) - << endmsg; - return; - } - - if (yn) { - - play_loop = true; - have_looped = false; - - if (loc) { - - unset_play_range (); - /* set all tracks to use internal looping */ - set_track_loop (true); - - merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f)); - - if (!Config->get_loop_is_mode()) { - /* args: positition, roll=true, flush=true, for_loop_end=false, force buffer, refill looping */ - - TFSM_LOCATE (loc->start(), true, true, false, true); - } - } - - } else { - - unset_play_loop (); - } - - DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed)); - TransportStateChange (); -} - /* ***************************************************************************** * END REALTIME ACTIONS * ****************************************************************************/ - void Session::add_post_transport_work (PostTransportWork ptw) { @@ -1069,28 +1016,9 @@ Session::request_play_loop (bool yn, bool change_transport_roll) target_speed = transport_speed (); } - ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn); + ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn, change_transport_roll); DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll)); queue_event (ev); - - if (yn) { - - if (!change_transport_roll) { - if (!Config->get_loop_is_mode() && !transport_rolling()) { - /* we're not changing transport state, but we do want - to set up position for the new loop. Don't - do this if we're rolling already. - */ - request_locate (location->start(), false); - } - } - } else { - if (!change_transport_roll && transport_rolling()) { - // request an immediate locate to refresh the tracks - // after disabling looping - request_locate (_transport_sample-1, false); - } - } } void @@ -1646,15 +1574,74 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) } void -Session::unset_play_loop () +Session::set_play_loop (bool yn, bool change_transport_state) +{ + ENSURE_PROCESS_THREAD; + /* Called from event-handling context */ + + DEBUG_TRACE (DEBUG::Transport, string_compose ("set_play_loop (%1)\n", yn)); + + Location *loc; + + if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) { + /* nothing to do, or can't change loop status while recording */ + return; + } + + if (yn && synced_to_engine()) { + warning << string_compose ( + _("Looping cannot be supported while %1 is using JACK transport.\n" + "Recommend changing the configured options"), PROGRAM_NAME) + << endmsg; + return; + } + + if (yn) { + + play_loop = true; + have_looped = false; + + if (loc) { + + unset_play_range (); + /* set all tracks to use internal looping */ + set_track_loop (true); + + merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f)); + + if (!Config->get_loop_is_mode() && !transport_rolling()) { + /* args: positition, roll=true, flush=true, for_loop_end=false, force buffer, refill looping */ + + TFSM_LOCATE (loc->start(), true, true, false, true); + } + } + + } else { + + unset_play_loop (); + } + + DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed)); + TransportStateChange (); +} + +void +Session::unset_play_loop (bool change_transport_state) { if (play_loop) { + play_loop = false; clear_events (SessionEvent::AutoLoop); set_track_loop (false); + /* likely need to flush track buffers: this will locate us to wherever we are */ - add_post_transport_work (PostTransportLocate); - TFSM_EVENT (TransportFSM::ButlerRequired); + + if (change_transport_state && transport_rolling ()) { + TFSM_EVENT (TransportFSM::StopTransport); + } + + overwrite_some_buffers (boost::shared_ptr()); + TransportStateChange (); /* EMIT SIGNAL */ } } -- cgit v1.2.3