summaryrefslogtreecommitdiff
path: root/libs/ardour/session_transport.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-02-16 19:30:21 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2015-02-16 19:35:37 -0500
commitb3e7c88988b6b3ade5872935b7c371cf3a6a1040 (patch)
tree4f57a431ca35af5e341271205c9167fa35a7edf8 /libs/ardour/session_transport.cc
parentdd8f2cfe18c8ba1b4863e029d32e10442b8f396e (diff)
fixes for desirable playback when using seamless looping.
Try to make sure that we appropriately reset and refill track buffers whenever we enter/leave loop playback,and whenever we locate. In addition, if we start playing somewhere other than the loop range while loop is enabled, then the first time we hit the loop end, set up the track buffers. Conflicts: libs/ardour/session_transport.cc
Diffstat (limited to 'libs/ardour/session_transport.cc')
-rw-r--r--libs/ardour/session_transport.cc77
1 files changed, 68 insertions, 9 deletions
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 2ed6279936..fa1c0c31d0 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -449,14 +449,33 @@ Session::non_realtime_locate ()
DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
if (Config->get_loop_is_mode() && get_play_loop()) {
+
Location *loc = _locations->auto_loop_location();
+
if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
/* jumped out of loop range: stop tracks from looping,
but leave loop (mode) enabled.
*/
set_track_loop (false);
+
+ } else if (loc && Config->get_seamless_loop() && (loc->start() == _transport_frame)) {
+
+ /* jumping to start of loop. This might have been done before but it is
+ * idempotent and cheap. Doing it here ensures that when we start playback
+ * outside the loop we still flip tracks into the magic seamless mode
+ * when needed.
+ */
+ set_track_loop (true);
+
+ } else if (loc) {
+ set_track_loop (false);
}
+
+ } else {
+
+ /* no more looping .. should have been noticed elsewhere */
}
+
boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@@ -765,6 +784,12 @@ Session::unset_play_loop ()
clear_events (SessionEvent::AutoLoop);
clear_events (SessionEvent::AutoLoopDeclick);
set_track_loop (false);
+
+ if (Config->get_seamless_loop()) {
+ /* likely need to flush track buffers: this will locate us to wherever we are */
+ add_post_transport_work (PostTransportLocate);
+ _butler->schedule_transport_work ();
+ }
}
void
@@ -775,9 +800,9 @@ Session::set_track_loop (bool yn)
if (!loc) {
yn = false;
}
-
- // set all tracks to NOT use internal looping
+
boost::shared_ptr<RouteList> rl = routes.reader ();
+
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
if (tr && !tr->hidden()) {
@@ -809,16 +834,23 @@ Session::set_play_loop (bool yn, double speed)
if (yn) {
play_loop = true;
-
+ have_looped = false;
+
if (loc) {
unset_play_range ();
if (Config->get_seamless_loop()) {
- // set all tracks to use internal looping
- set_track_loop (true);
+ if (!Config->get_loop_is_mode()) {
+ /* set all tracks to use internal looping */
+ set_track_loop (true);
+ } else {
+ /* we will do this in the locate to the start OR when we hit the end
+ * of the loop for the first time
+ */
+ }
} else {
- // set all tracks to NOT use internal looping
+ /* set all tracks to NOT use internal looping */
set_track_loop (false);
}
@@ -947,6 +979,9 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
* changes in the value of _transport_frame.
*/
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 seamless %4 force %5 mmc %6\n",
+ target_frame, with_roll, with_flush, for_seamless_loop, force, with_mmc));
+
if (actively_recording() && !for_seamless_loop) {
return;
}
@@ -993,7 +1028,7 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
*/
bool transport_was_stopped = !transport_rolling();
-
+
if (transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop)) {
realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
transport_was_stopped = true;
@@ -1011,7 +1046,6 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
}
add_post_transport_work (todo);
- _butler->schedule_transport_work ();
} else {
@@ -1051,10 +1085,18 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
// located outside the loop: cancel looping directly, this is called from event handling context
+ have_looped = false;
+
if (!Config->get_loop_is_mode()) {
set_play_loop (false, _transport_speed);
} else {
- /* handled in ::non_realtime_locate() */
+ if (Config->get_seamless_loop()) {
+ /* this will make the non_realtime_locate() in the butler
+ which then causes seek() in tracks actually do the right
+ thing.
+ */
+ set_track_loop (false);
+ }
}
} else if (_transport_frame == al->start()) {
@@ -1063,6 +1105,18 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
if (for_seamless_loop) {
+ if (!have_looped) {
+ /* first time */
+ if (_last_roll_location != al->start()) {
+ /* didn't start at loop start - playback must have
+ * started before loop since we've now hit the loop
+ * end.
+ */
+ add_post_transport_work (PostTransportLocate);
+ }
+
+ }
+
// this is only necessary for seamless looping
boost::shared_ptr<RouteList> rl = routes.reader();
@@ -1083,6 +1137,8 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
}
}
+ _butler->schedule_transport_work ();
+
loop_changing = false;
_send_timecode_update = true;
@@ -1172,11 +1228,14 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a
if (location != 0) {
if (_transport_frame != location->start()) {
+
if (Config->get_seamless_loop()) {
/* force tracks to do their thing */
set_track_loop (true);
}
+
/* jump to start and then roll from there */
+
request_locate (location->start(), true);
return;
}