if a request to reset the speed to zero as the default arrives when stopped, reset...
[ardour.git] / libs / ardour / session_transport.cc
index 20ac7375759cac2150da73433ac5c8c3b287dbca..4f0fb90c53a6d76ccb2357be9aceff248c76ace7 100644 (file)
@@ -103,10 +103,11 @@ Session::request_sync_source (Slave* new_slave)
 }
 
 void
-Session::request_transport_speed (double speed)
+Session::request_transport_speed (double speed, bool as_default)
 {
        SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
-       DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
+       ev->third_yes_or_no = true;
+       DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
        queue_event (ev);
 }
 
@@ -115,13 +116,13 @@ Session::request_transport_speed (double speed)
  *  be used by callers who are varying transport speed but don't ever want to stop it.
  */
 void
-Session::request_transport_speed_nonzero (double speed)
+Session::request_transport_speed_nonzero (double speed, bool as_default)
 {
        if (speed == 0) {
                speed = DBL_EPSILON;
        }
 
-       request_transport_speed (speed);
+       request_transport_speed (speed, as_default);
 }
 
 void
@@ -298,8 +299,8 @@ Session::butler_transport_work ()
                        if (tr) {
                                tr->adjust_playback_buffering ();
                                /* and refill those buffers ... */
-                               tr->non_realtime_locate (_transport_frame);
                        }
+                       (*i)->non_realtime_locate (_transport_frame);
                }
 
        }
@@ -343,10 +344,8 @@ Session::butler_transport_work ()
                if (!(ptw & PostTransportLocate)) {
 
                        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                               boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
-                               if (tr && !tr->hidden()) {
-                                       tr->non_realtime_locate (_transport_frame);
-                               }
+                               (*i)->non_realtime_locate (_transport_frame);
+
                                if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
                                        /* new request, stop seeking, and start again */
                                        g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
@@ -419,10 +418,7 @@ Session::non_realtime_locate ()
 {
        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->non_realtime_locate (_transport_frame);
-               }
+               (*i)->non_realtime_locate (_transport_frame);
        }
 
        /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
@@ -600,10 +596,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
        DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
-               boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
-               if (tr && !tr->hidden()) {
-                       tr->non_realtime_locate (_transport_frame);
-               }
+               (*i)->non_realtime_locate (_transport_frame);
 
                if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
                        finished = false;
@@ -645,6 +638,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
        }
 
        PositionChanged (_transport_frame); /* EMIT SIGNAL */
+       DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
        TransportStateChange (); /* EMIT SIGNAL */
 
        /* and start it up again if relevant */
@@ -773,6 +767,7 @@ Session::set_play_loop (bool yn)
                unset_play_loop ();
        }
 
+       DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
        TransportStateChange ();
 }
 void
@@ -797,6 +792,14 @@ Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush,
 
                if (target_frame != pos) {
 
+                       if (config.get_jack_time_master()) {
+                               /* actually locate now, since otherwise jack_timebase_callback
+                                  will use the incorrect _transport_frame and report an old
+                                  and incorrect time to Jack transport
+                               */
+                               locate (target_frame, with_roll, with_flush, with_loop, force);
+                       }
+
                        /* tell JACK to change transport position, and we will
                           follow along later in ::follow_slave()
                        */
@@ -879,6 +882,7 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
        // Update Timecode time
        // [DR] FIXME: find out exactly where this should go below
        _transport_frame = target_frame;
+       _last_roll_or_reversal_location = target_frame;
        timecode_time(_transport_frame, transmitting_timecode_time);
        outbound_mtc_timecode_frame = _transport_frame;
        next_quarter_frame_to_send = 0;
@@ -917,7 +921,7 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
 
                /* this is functionally what clear_clicks() does but with a tentative lock */
 
-               Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
+               Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
 
                if (clickm.locked()) {
 
@@ -995,12 +999,15 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
  *  @param speed New speed
  */
 void
-Session::set_transport_speed (double speed, bool abort, bool clear_state)
+Session::set_transport_speed (double speed, bool abort, bool clear_state, bool as_default)
 {
-       DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4\n", 
-                                                      speed, abort, clear_state, _transport_speed, _transport_frame));
+       DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n", 
+                                                      speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
 
        if (_transport_speed == speed) {
+               if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
+                       _default_transport_speed = 1.0;
+               }
                return;
        }
 
@@ -1098,6 +1105,10 @@ Session::set_transport_speed (double speed, bool abort, bool clear_state)
                _last_transport_speed = _transport_speed;
                _transport_speed = speed;
 
+               if (as_default) {
+                       _default_transport_speed = speed;
+               }
+
                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);
@@ -1111,6 +1122,7 @@ Session::set_transport_speed (double speed, bool abort, bool clear_state)
                        _butler->schedule_transport_work ();
                }
 
+               DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
                TransportStateChange (); /* EMIT SIGNAL */
        }
 }
@@ -1213,7 +1225,7 @@ Session::start_transport ()
 
        transport_sub_state |= PendingDeclickIn;
 
-       _transport_speed = 1.0;
+       _transport_speed = _default_transport_speed;
        _target_transport_speed = _transport_speed;
 
        boost::shared_ptr<RouteList> rl = routes.reader();
@@ -1222,7 +1234,6 @@ Session::start_transport ()
                if (tr) {
                        tr->realtime_set_speed (tr->speed(), true);
                }
-               (*i)->automation_snapshot (_transport_frame, true);
        }
 
        if (!_engine.freewheeling()) {
@@ -1233,6 +1244,7 @@ Session::start_transport ()
                }
        }
 
+       DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
        TransportStateChange (); /* EMIT SIGNAL */
 }
 
@@ -1481,6 +1493,7 @@ Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
        ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
        merge_event (ev);
 
+       DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
        TransportStateChange ();
 }
 
@@ -1523,6 +1536,7 @@ Session::engine_halted ()
        non_realtime_stop (false, 0, ignored);
        transport_sub_state = 0;
 
+       DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
        TransportStateChange (); /* EMIT SIGNAL */
 }