commits 6001-6525 inclusive from 2.X applied to 3.0
[ardour.git] / libs / ardour / session_transport.cc
index a632ae067da874b642c9be640d414bce8b8bf4ea..c5e6795325e41fbb61197169bf5b8a7bea1ca7d0 100644 (file)
@@ -21,8 +21,6 @@
 #include <cerrno>
 #include <unistd.h>
 
-#include <sigc++/bind.h>
-#include <sigc++/retype.h>
 
 #include "pbd/undo.h"
 #include "pbd/error.h"
@@ -47,7 +45,6 @@
 
 using namespace std;
 using namespace ARDOUR;
-using namespace sigc;
 using namespace PBD;
 
 void
@@ -200,10 +197,17 @@ Session::realtime_stop (bool abort, bool clear_state)
 
                /* move the transport position back to where the
                   request for a stop was noticed. we rolled
-                  past that point to pick up delayed input.
+                  past that point to pick up delayed input (and/or to delick)
                */
 
-               decrement_transport_position (_worst_output_latency);
+                if (_worst_output_latency > current_block_size) {
+                        /* we rolled past the stop point to pick up data that had
+                           not yet arrived. move back to where the stop occured.
+                        */
+                        decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
+                } else {
+                        decrement_transport_position (current_block_size);
+                }
 
                /* the duration change is not guaranteed to have happened, but is likely */
 
@@ -226,8 +230,9 @@ Session::realtime_stop (bool abort, bool clear_state)
        _clear_event_type (SessionEvent::RangeStop);
        _clear_event_type (SessionEvent::RangeLocate);
 
-       disable_record (true);
-
+        /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
+       disable_record (true, (!Config->get_latched_record_enable() && clear_state));
+        
        reset_slave_state ();
 
        _transport_speed = 0;
@@ -319,6 +324,8 @@ Session::butler_transport_work ()
        }
 
        g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
+
+       DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
 }
 
 void
@@ -396,7 +403,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
        if (did_record) {
                begin_reversible_command ("capture");
 
-               Location* loc = _locations.end_location();
+               Location* loc = _locations.session_range_location();
                bool change_end = false;
 
                if (_transport_frame < loc->end()) {
@@ -428,6 +435,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                _have_captured = true;
        }
 
+       DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
        for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
                (*i)->transport_stopped (*now, xnow, abort);
        }
@@ -463,7 +471,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
                    !(ptw & PostTransportLocate)) {
 
-       /* no explicit locate queued */
+                        /* no explicit locate queued */
 
                        bool do_locate = false;
 
@@ -534,10 +542,14 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
        /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
 
 
+       DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
+
        for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
                if (!(*i)->hidden()) {
+                        DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
                        (*i)->non_realtime_locate (_transport_frame);
                }
+
                if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
                        finished = false;
                        /* we will be back */
@@ -643,8 +655,8 @@ Session::set_play_loop (bool yn)
        set_dirty();
        
        if (yn && Config->get_seamless_loop() && synced_to_jack()) {
-               warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
-                            "Recommend changing the configured options")
+               warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
+                                             "Recommend changing the configured options"), PROGRAM_NAME)
                        << endmsg;
                return;
        }
@@ -936,10 +948,6 @@ Session::set_transport_speed (double speed, bool abort, bool clear_state)
 
                /* we are stopped and we want to start rolling at speed 1 */
 
-               if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
-                       return;
-               }
-
                if (Config->get_monitoring_model() == HardwareMonitoring) {
 
                        boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
@@ -960,14 +968,9 @@ Session::set_transport_speed (double speed, bool abort, bool clear_state)
 
        } else {
 
-               /* if not recording, don't roll forward past end if told to stop there */
-
-               if (!get_record_enabled() && (speed > 0.0 && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame())) {
-                       return;
-               }
-
                if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
-                       warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
+                       warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
+                                                   PROGRAM_NAME)
                                << endmsg;
                        return;
                }
@@ -1023,9 +1026,13 @@ Session::stop_transport (bool abort, bool clear_state)
                return;
        }
 
-       if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
-           _worst_output_latency > current_block_size)
-       {
+       if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
+
+                boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+                for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+                        (*i)->prepare_to_stop (_transport_frame);
+                }
 
                /* we need to capture the audio that has still not yet been received by the system
                   at the time the stop is requested, so we have to roll past that time.
@@ -1047,6 +1054,15 @@ Session::stop_transport (bool abort, bool clear_state)
 
 
        if ((transport_sub_state & PendingDeclickOut) == 0) {
+
+                if (!(transport_sub_state & StopPendingCapture)) {
+                        boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+                        
+                        for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+                                (*i)->prepare_to_stop (_transport_frame);
+                        }
+                }
+                
                transport_sub_state |= PendingDeclickOut;
                /* we'll be called again after the declick */
                pending_abort = abort;
@@ -1108,7 +1124,7 @@ Session::post_transport ()
        PostTransportWork ptw = post_transport_work ();
 
        if (ptw & PostTransportAudition) {
-               if (auditioner && auditioner->active()) {
+               if (auditioner && auditioner->auditioning()) {
                        process_function = &Session::process_audition;
                } else {
                        process_function = &Session::process_with_events;
@@ -1426,6 +1442,7 @@ Session::route_processors_changed (RouteProcessorChange c)
        }
 
        update_latency_compensation (false, false);
+       resort_routes ();
 }
 
 void