fix reset of transport speed when seamless looping; add a few comments and tidy-ups to related transport code

git-svn-id: svn://localhost/ardour2/branches/3.0@12818 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2012-06-22 14:27:51 +00:00
parent d70429a066
commit 8c10320497
5 changed files with 64 additions and 34 deletions

View file

@ -648,6 +648,9 @@ ShuttleControl::parameter_changed (std::string p)
if (_session->transport_speed() == 1.0) { if (_session->transport_speed() == 1.0) {
queue_draw (); queue_draw ();
} else { } else {
/* reset current speed and
revert to 1.0 as the default
*/
_session->request_transport_speed (1.0); _session->request_transport_speed (1.0);
/* redraw when speed changes */ /* redraw when speed changes */
} }

View file

@ -1015,6 +1015,9 @@ Session::process_event (SessionEvent* ev)
case SessionEvent::AutoLoop: case SessionEvent::AutoLoop:
if (play_loop) { if (play_loop) {
/* roll after locate, do not flush, set "with loop"
true only if we are seamless looping
*/
start_locate (ev->target_frame, true, false, Config->get_seamless_loop()); start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
} }
remove = false; remove = false;
@ -1034,10 +1037,10 @@ Session::process_event (SessionEvent* ev)
case SessionEvent::Locate: case SessionEvent::Locate:
if (ev->yes_or_no) { if (ev->yes_or_no) {
// cerr << "forced locate to " << ev->target_frame << endl; /* args: do not roll after locate, do flush, not with loop */
locate (ev->target_frame, false, true, false); locate (ev->target_frame, false, true, false);
} else { } else {
// cerr << "soft locate to " << ev->target_frame << endl; /* args: do not roll after locate, do flush, not with loop */
start_locate (ev->target_frame, false, true, false); start_locate (ev->target_frame, false, true, false);
} }
_send_timecode_update = true; _send_timecode_update = true;
@ -1045,10 +1048,10 @@ Session::process_event (SessionEvent* ev)
case SessionEvent::LocateRoll: case SessionEvent::LocateRoll:
if (ev->yes_or_no) { if (ev->yes_or_no) {
// cerr << "forced locate to+roll " << ev->target_frame << endl; /* args: roll after locate, do flush, not with loop */
locate (ev->target_frame, true, true, false); locate (ev->target_frame, true, true, false);
} else { } else {
// cerr << "soft locate to+roll " << ev->target_frame << endl; /* args: roll after locate, do flush, not with loop */
start_locate (ev->target_frame, true, true, false); start_locate (ev->target_frame, true, true, false);
} }
_send_timecode_update = true; _send_timecode_update = true;
@ -1101,6 +1104,7 @@ Session::process_event (SessionEvent* ev)
break; break;
case SessionEvent::RangeLocate: case SessionEvent::RangeLocate:
/* args: roll after locate, do flush, not with loop */
start_locate (ev->target_frame, true, true, false); start_locate (ev->target_frame, true, true, false);
remove = false; remove = false;
del = false; del = false;

View file

@ -760,8 +760,9 @@ Session::set_play_loop (bool yn)
merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f)); merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f)); merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
/* locate to start of loop and roll. If doing seamless loop, force a /* locate to start of loop and roll.
locate+buffer refill even if we are positioned there already.
args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
*/ */
start_locate (loc->start(), true, true, false, Config->get_seamless_loop()); start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
@ -837,13 +838,21 @@ Session::micro_locate (framecnt_t distance)
/** @param with_mmc true to send a MMC locate command when the locate is done */ /** @param with_mmc true to send a MMC locate command when the locate is done */
void void
Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc) Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_seamless_loop, bool force, bool with_mmc)
{ {
if (actively_recording() && !with_loop) { /* Locates for seamless looping are fairly different from other
* locates. They assume that the diskstream buffers for each track
* already have the correct data in them, and thus there is no need to
* actually tell the tracks to locate. What does need to be done,
* though, is all the housekeeping that is associated with non-linear
* changes in the value of _transport_frame.
*/
if (actively_recording() && !for_seamless_loop) {
return; return;
} }
if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) { if (!force && _transport_frame == target_frame && !loop_changing && !for_seamless_loop) {
if (with_roll) { if (with_roll) {
set_transport_speed (1.0, false); set_transport_speed (1.0, false);
} }
@ -852,10 +861,10 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
return; return;
} }
if (_transport_speed && !with_loop) { if (_transport_speed && !for_seamless_loop) {
/* Schedule a declick. We'll be called again when its done. /* Schedule a declick. We'll be called again when its done.
We only do it this way for ordinary locates, not those We only do it this way for ordinary locates, not those
due to loops. due to **seamless** loops.
*/ */
if (!(transport_sub_state & PendingDeclickOut)) { if (!(transport_sub_state & PendingDeclickOut)) {
@ -883,18 +892,21 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
* *
*/ */
if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) { bool transport_was_stopped = !transport_rolling();
if (transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
transport_was_stopped = true;
} else { } else {
/* otherwise tell the world that we located */ /* otherwise tell the world that we located */
realtime_locate (); realtime_locate ();
} }
if (force || !with_loop || loop_changing) { if (force || !for_seamless_loop || loop_changing) {
PostTransportWork todo = PostTransportLocate; PostTransportWork todo = PostTransportLocate;
if (with_roll) { if (with_roll && transport_was_stopped) {
todo = PostTransportWork (todo | PostTransportRoll); todo = PostTransportWork (todo | PostTransportRoll);
} }
@ -931,29 +943,41 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
/* cancel looped playback if transport pos outside of loop range */ /* cancel looped playback if transport pos outside of loop range */
if (play_loop) { if (play_loop) {
Location* al = _locations->auto_loop_location(); Location* al = _locations->auto_loop_location();
if (al && (_transport_frame < al->start() || _transport_frame > al->end())) { if (al) {
// cancel looping directly, this is called from event handling context if (_transport_frame < al->start() || _transport_frame > al->end()) {
// located outside the loop: cancel looping directly, this is called from event handling context
set_play_loop (false); set_play_loop (false);
}
else if (al && _transport_frame == al->start()) { } else if (_transport_frame == al->start()) {
if (with_loop) {
// located to start of loop - this is looping, basically
if (for_seamless_loop) {
// this is only necessary for seamless looping // this is only necessary for seamless looping
boost::shared_ptr<RouteList> rl = routes.reader(); boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i); boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
if (tr && tr->record_enabled ()) { if (tr && tr->record_enabled ()) {
// tell it we've looped, so it can deal with the record state // tell it we've looped, so it can deal with the record state
tr->transport_looped (_transport_frame); tr->transport_looped (_transport_frame);
} }
} }
} }
have_looped = true; have_looped = true;
TransportLooped(); // EMIT SIGNAL TransportLooped(); // EMIT SIGNAL
} }
} }
}
loop_changing = false; loop_changing = false;
@ -1190,7 +1214,7 @@ Session::start_transport ()
transport_sub_state |= PendingDeclickIn; transport_sub_state |= PendingDeclickIn;
_transport_speed = 1.0; _transport_speed = 1.0;
_target_transport_speed = 1.0; _target_transport_speed = _transport_speed;
boost::shared_ptr<RouteList> rl = routes.reader(); boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@ -1237,7 +1261,6 @@ Session::post_transport ()
if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) { if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
start_transport (); start_transport ();
} else { } else {
transport_sub_state = 0; transport_sub_state = 0;
} }