merge fix
[ardour.git] / libs / ardour / session_transport.cc
index 711c3e51e71eeca640df6f9717511a12da021e23..51734a06c0ba4a280e0b737556a20d4095eba86f 100644 (file)
@@ -314,12 +314,13 @@ Session::butler_transport_work ()
        bool finished;
        PostTransportWork ptw;
        boost::shared_ptr<RouteList> r = routes.reader ();
-
+       uint64_t before;
+       
        int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
        finished = true;
        ptw = post_transport_work();
 
-       DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), g_get_monotonic_time()));
+       DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
 
        if (ptw & PostTransportAdjustPlaybackBuffering) {
                for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
@@ -410,7 +411,7 @@ Session::butler_transport_work ()
 
        g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
 
-       DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done at %1\n"), g_get_monotonic_time()));
+       DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
        DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
 }
 
@@ -493,6 +494,106 @@ Session::non_realtime_locate ()
        clear_clicks ();
 }
 
+#ifdef USE_TRACKS_CODE_FEATURES
+bool
+Session::select_playhead_priority_target (framepos_t& jump_to)
+{
+       jump_to = -1;
+
+       AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
+
+       if (!autoreturn) {
+               return false;
+       }
+
+       if (Profile->get_trx() && transport_rolling() ) {
+               // We're playing, so do nothing.
+               // Next stop will put us where we need to be.
+               return false;
+       }
+       
+       /* Note that the order of checking each AutoReturnTarget flag defines
+          the priority each flag.
+
+          Ardour/Mixbus: Last Locate
+                         Range Selection
+                         Loop Range
+                         Region Selection
+
+          Tracks:        Range Selection
+                          Loop Range
+                          Region Selection
+                          Last Locate
+       */
+       
+       if (autoreturn & RangeSelectionStart) {
+               if (!_range_selection.empty()) {
+                       jump_to = _range_selection.from;
+               } else {
+                       if (transport_rolling ()) {
+                               /* Range selection no longer exists, but we're playing,
+                                  so do nothing. Next stop will put us where
+                                  we need to be.
+                               */
+                               return false;
+                       }
+               }
+       }
+       
+       if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
+               /* don't try to handle loop play when synced to JACK */
+               
+               if (!synced_to_engine()) {
+                       Location *location = _locations->auto_loop_location();
+                       
+                       if (location) {
+                               jump_to = location->start();
+
+                               if (Config->get_seamless_loop()) {
+                                       /* need to get track buffers reloaded */
+                                       set_track_loop (true);
+                               }
+                       } 
+               }
+       }
+       
+       if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
+               if (!_object_selection.empty()) {
+                       jump_to = _object_selection.from;
+               }
+       } 
+
+       if (jump_to < 0 && (autoreturn & LastLocate)) {
+               jump_to = _last_roll_location;
+       }
+       
+       return jump_to >= 0;
+}
+#else
+
+bool
+Session::select_playhead_priority_target (framepos_t& jump_to)
+{
+       if (!config.get_auto_return()) {
+               return false;
+       }
+
+       jump_to = _last_roll_location;
+       return jump_to >= 0;
+}
+
+#endif
+
+void
+Session::follow_playhead_priority ()
+{
+       framepos_t target;
+
+       if (select_playhead_priority_target (target)) {
+               request_locate (target);
+       }
+}
+
 void
 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
 {
@@ -575,8 +676,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                update_latency_compensation ();
        }
 
-       bool const auto_return_enabled =
-               (!config.get_external_sync() && (config.get_auto_return() || abort));
+       bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
 
        if (auto_return_enabled ||
            (ptw & PostTransportLocate) ||
@@ -602,40 +702,13 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                                do_locate = true;
 
                        } else {
-                               if (config.get_auto_return()) {
+                               framepos_t jump_to;
 
-                                       if (play_loop) {
+                               if (select_playhead_priority_target (jump_to)) {
 
-                                               /* don't try to handle loop play when synced to JACK */
-
-                                               if (!synced_to_engine()) {
-
-                                                       Location *location = _locations->auto_loop_location();
-
-                                                       if (location != 0) {
-                                                               _transport_frame = location->start();
-                                                       } else {
-                                                               _transport_frame = _last_roll_location;
-                                                       }
-                                                       do_locate = true;
-                                               }
-
-                                       } else if (_play_range) {
-
-                                               /* return to start of range */
-
-                                               if (!current_audio_range.empty()) {
-                                                       _transport_frame = current_audio_range.front().start;
-                                                       do_locate = true;
-                                               }
-
-                                       } else {
-
-                                               /* regular auto-return */
+                                       _transport_frame = jump_to;
+                                       do_locate = true;
 
-                                               _transport_frame = _last_roll_location;
-                                               do_locate = true;
-                                       }
                                } else if (abort) {
 
                                        _transport_frame = _last_roll_location;
@@ -1217,7 +1290,7 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a
                        }
                        _engine.transport_stop ();
                } else {
-                       bool const auto_return_enabled = (!config.get_external_sync() && (config.get_auto_return() || abort));
+                       bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
 
                        if (!auto_return_enabled) {
                                _requested_return_frame = destination_frame;
@@ -1550,6 +1623,13 @@ Session::mtc_status_changed (bool yn)
        MTCSyncStateChanged( yn );
 }
 
+void
+Session::ltc_status_changed (bool yn)
+{
+       g_atomic_int_set (&_ltc_active, yn);
+       LTCSyncStateChanged( yn );
+}
+
 void
 Session::use_sync_source (Slave* new_slave)
 {
@@ -1574,6 +1654,18 @@ Session::use_sync_source (Slave* new_slave)
                mtc_status_connection.disconnect ();
        }
 
+       LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
+       if (ltc_slave) {
+               ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
+               LTCSyncStateChanged (ltc_slave->locked() );
+       } else {
+               if (g_atomic_int_get (&_ltc_active) ){
+                       g_atomic_int_set (&_ltc_active, 0);
+                       LTCSyncStateChanged( false );
+               }
+               ltc_status_connection.disconnect ();
+       }
+
        DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
        
        // need to queue this for next process() cycle