mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
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:
parent
d70429a066
commit
8c10320497
5 changed files with 64 additions and 34 deletions
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -329,7 +329,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
void goto_start ();
|
void goto_start ();
|
||||||
void use_rf_shuttle_speed ();
|
void use_rf_shuttle_speed ();
|
||||||
void allow_auto_play (bool yn);
|
void allow_auto_play (bool yn);
|
||||||
void request_transport_speed (double speed);
|
void request_transport_speed (double speed);
|
||||||
void request_transport_speed_nonzero (double);
|
void request_transport_speed_nonzero (double);
|
||||||
void request_overwrite_buffer (Track *);
|
void request_overwrite_buffer (Track *);
|
||||||
void adjust_playback_buffering();
|
void adjust_playback_buffering();
|
||||||
|
|
@ -1210,7 +1210,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
void start_locate (framepos_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
|
void start_locate (framepos_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
|
||||||
void force_locate (framepos_t frame, bool with_roll = false);
|
void force_locate (framepos_t frame, bool with_roll = false);
|
||||||
void set_track_speed (Track *, double speed);
|
void set_track_speed (Track *, double speed);
|
||||||
void set_transport_speed (double speed, bool abort = false, bool clear_state = false);
|
void set_transport_speed (double speed, bool abort = false, bool clear_state = false);
|
||||||
void stop_transport (bool abort = false, bool clear_state = false);
|
void stop_transport (bool abort = false, bool clear_state = false);
|
||||||
void start_transport ();
|
void start_transport ();
|
||||||
void realtime_stop (bool abort, bool clear_state);
|
void realtime_stop (bool abort, bool clear_state);
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ public:
|
||||||
|
|
||||||
boost::shared_ptr<Region> region;
|
boost::shared_ptr<Region> region;
|
||||||
|
|
||||||
SessionEvent (Type t, Action a, framepos_t when, framepos_t where, double spd, bool yn = false, bool yn2 = false)
|
SessionEvent (Type t, Action a, framepos_t when, framepos_t where, double spd, bool yn = false, bool yn2 = false)
|
||||||
: type (t)
|
: type (t)
|
||||||
, action (a)
|
, action (a)
|
||||||
, action_frame (when)
|
, action_frame (when)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,27 +943,39 @@ 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()) {
|
||||||
set_play_loop (false);
|
|
||||||
}
|
|
||||||
else if (al && _transport_frame == al->start()) {
|
|
||||||
if (with_loop) {
|
|
||||||
// this is only necessary for seamless looping
|
|
||||||
|
|
||||||
boost::shared_ptr<RouteList> rl = routes.reader();
|
// located outside the loop: cancel looping directly, this is called from event handling context
|
||||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
|
||||||
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
|
set_play_loop (false);
|
||||||
if (tr && tr->record_enabled ()) {
|
|
||||||
// tell it we've looped, so it can deal with the record state
|
} else if (_transport_frame == al->start()) {
|
||||||
tr->transport_looped(_transport_frame);
|
|
||||||
|
// located to start of loop - this is looping, basically
|
||||||
|
|
||||||
|
if (for_seamless_loop) {
|
||||||
|
|
||||||
|
// this is only necessary for seamless 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->record_enabled ()) {
|
||||||
|
// tell it we've looped, so it can deal with the record state
|
||||||
|
tr->transport_looped (_transport_frame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
have_looped = true;
|
||||||
|
TransportLooped(); // EMIT SIGNAL
|
||||||
}
|
}
|
||||||
have_looped = true;
|
|
||||||
TransportLooped(); // EMIT SIGNAL
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue