changes to use overwrite-buffers when loop is disabled or loop range changed

This commit is contained in:
Paul Davis 2019-12-05 13:00:24 -07:00
parent 551702b9e9
commit 8b4e714006
5 changed files with 90 additions and 93 deletions

View File

@ -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<Route>);
void flush_all_inserts ();
int micro_locate (samplecnt_t distance);

View File

@ -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) {
// schedule a locate-roll to refill the diskstreams at the
// previous loop end
loop_changing = true;
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);
}
}
// schedule a buffer overwrite to refill buffers with the new loop.
request_overwrite_buffer (boost::shared_ptr<Track>());
}
} else {

View File

@ -89,10 +89,15 @@ Session::request_overwrite_buffer (boost::shared_ptr<Track> t)
queue_event (ev);
}
/** Process thread. */
void
Session::overwrite_some_buffers (boost::shared_ptr<Route> 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;
}

View File

@ -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<Route>());
break;
case SessionEvent::Audition:
set_audition (ev->region);
// drop reference to region

View File

@ -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<Route>());
TransportStateChange (); /* EMIT SIGNAL */
}
}