remove Tracks runtime conditional, incorrectly added during manual merging
[ardour.git] / libs / ardour / session_transport.cc
index fa1c0c31d01e6dab387b9e045e82a2820546555d..42ef46ca257e34f7a76ef3206050dc1b780a6328 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\n", enum_2_string (ptw)));
+       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, X_("Butler transport work all done\n"));
+       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)));
 }
 
@@ -458,7 +459,9 @@ Session::non_realtime_locate ()
                         */
                        set_track_loop (false);
 
-               } else if (loc && Config->get_seamless_loop() && (loc->start() == _transport_frame)) {
+               } else if (loc && Config->get_seamless_loop() &&
+                   ((loc->start() <= _transport_frame) ||
+                   (loc->end() > _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
@@ -491,6 +494,101 @@ Session::non_realtime_locate ()
        clear_clicks ();
 }
 
+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
+       */
+       
+#ifndef USE_TRACKS_CODE_FEATURES
+       if (autoreturn & LastLocate) {
+               jump_to = _last_roll_location;
+       }
+       
+       if (jump_to < 0 && (autoreturn & RangeSelectionStart)) {
+#else
+       if (autoreturn & RangeSelectionStart) {
+#endif
+               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)) {
+               /* 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;
+               }
+       } 
+
+#ifdef USE_TRACKS_CODE_FEATURES
+       if (jump_to < 0 && (autoreturn & LastLocate)) {
+               jump_to = _last_roll_location;
+       }
+#endif
+       
+       return jump_to >= 0;
+}
+
+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)
 {
@@ -573,8 +671,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) ||
@@ -600,40 +697,13 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                                do_locate = true;
 
                        } else {
-                               if (config.get_auto_return()) {
-
-                                       if (play_loop) {
+                               framepos_t jump_to;
 
-                                               /* don't try to handle loop play when synced to JACK */
+                               if (select_playhead_priority_target (jump_to)) {
 
-                                               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;
@@ -780,15 +850,18 @@ Session::check_declick_out ()
 void
 Session::unset_play_loop ()
 {
-       play_loop = false;
-       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 ();
+       if (play_loop) {
+               play_loop = false;
+               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 ();
+               }
        }
 }
 
@@ -971,6 +1044,8 @@ Session::micro_locate (framecnt_t distance)
 void
 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_seamless_loop, bool force, bool with_mmc)
 {
+       bool need_butler = false;
+       
        /* 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
@@ -1028,8 +1103,9 @@ 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)) {
+
+       if (transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
+           (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
                realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
                transport_was_stopped = true;
        } else {
@@ -1046,7 +1122,8 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
                }
 
                add_post_transport_work (todo);
-
+               need_butler = true;
+               
        } else {
 
                /* this is functionally what clear_clicks() does but with a tentative lock */
@@ -1113,6 +1190,7 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
                                                         * end.
                                                         */
                                                        add_post_transport_work (PostTransportLocate);
+                                                       need_butler = true;
                                                }
                                                    
                                        }
@@ -1137,7 +1215,9 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
                }
        }
 
-       _butler->schedule_transport_work ();
+       if (need_butler) {
+               _butler->schedule_transport_work ();
+       }
 
        loop_changing = false;
 
@@ -1205,7 +1285,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;
@@ -1310,7 +1390,28 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a
                }
 
                DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
-               TransportStateChange (); /* EMIT SIGNAL */
+
+               /* throttle signal emissions. 
+                * when slaved [_last]_transport_speed
+                * usually changes every cycle (tiny amounts due to DLL).
+                * Emitting a signal every cycle is overkill and unwarranted.
+                *
+                * Using _last_transport_speed is not acceptable,
+                * since it allows for large changes over a long period 
+                * of time. Hence we introduce a dedicated variable to keep track
+                *
+                * The 0.2% dead-zone is somewhat arbitrary. Main use-case
+                * for TransportStateChange() here is the ShuttleControl display.
+                */
+               if (fabsf(_signalled_varispeed - speed) > .002f
+                   // still, signal hard changes to 1.0 and 0.0:
+                   || ( speed == 1.f && _signalled_varispeed != 1.f)
+                   || ( speed == 0.f && _signalled_varispeed != 0.f)
+                  )
+               {
+                       TransportStateChange (); /* EMIT SIGNAL */
+                       _signalled_varispeed = speed;
+               }
        }
 }
 
@@ -1510,6 +1611,13 @@ Session::reset_rf_scale (framecnt_t motion)
        }
 }
 
+void
+Session::mtc_status_changed (bool yn)
+{
+       g_atomic_int_set (&_mtc_active, yn);
+       MTCSyncStateChanged( yn );
+}
+
 void
 Session::use_sync_source (Slave* new_slave)
 {
@@ -1522,6 +1630,18 @@ Session::use_sync_source (Slave* new_slave)
        delete _slave;
        _slave = new_slave;
 
+       MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
+       if (mtc_slave) {
+               mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
+               MTCSyncStateChanged(mtc_slave->locked() );
+       } else {
+               if (g_atomic_int_get (&_mtc_active) ){
+                       g_atomic_int_set (&_mtc_active, 0);
+                       MTCSyncStateChanged( false );
+               }
+               mtc_status_connection.disconnect ();
+       }
+
        DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
        
        // need to queue this for next process() cycle
@@ -1757,8 +1877,6 @@ Session::engine_halted ()
        */
 
        if (_butler) {
-               g_atomic_int_set (&_butler->should_do_transport_work, 0);
-               set_post_transport_work (PostTransportWork (0));
                _butler->stop ();
        }
 
@@ -1774,6 +1892,8 @@ Session::engine_halted ()
 void
 Session::xrun_recovery ()
 {
+       ++_xrun_count;
+
        Xrun (_transport_frame); /* EMIT SIGNAL */
 
        if (Config->get_stop_recording_on_xrun() && actively_recording()) {
@@ -1794,6 +1914,12 @@ Session::route_processors_changed (RouteProcessorChange c)
        }
 
        if (c.type == RouteProcessorChange::MeterPointChange) {
+               set_dirty ();
+               return;
+       }
+
+       if (c.type == RouteProcessorChange::RealTimeChange) {
+               set_dirty ();
                return;
        }