Fix thinko in 9581cb26 - scratch-buffer can't be used recursively.
[ardour.git] / libs / ardour / session_transport.cc
index 4a729700abba183faf0dfbc4a0284dc1bc545688..65a9748ce60ebfe6187f533bac973cc2e140621d 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "ardour/audioengine.h"
 #include "ardour/auditioner.h"
+#include "ardour/automation_watch.h"
 #include "ardour/butler.h"
 #include "ardour/click.h"
 #include "ardour/debug.h"
@@ -216,6 +217,20 @@ Session::request_preroll_record_trim (framepos_t rec_in, framecnt_t preroll)
        set_requested_return_frame (rec_in);
 }
 
+void
+Session::request_count_in_record ()
+{
+       if (actively_recording ()) {
+               return;
+       }
+       if (transport_rolling()) {
+               return;
+       }
+       maybe_enable_record ();
+       _count_in_once = true;
+       request_transport_speed (1.0, true);
+}
+
 void
 Session::request_play_loop (bool yn, bool change_transport_roll)
 {
@@ -932,6 +947,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 */
+       AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
 
        /* and start it up again if relevant */
 
@@ -1351,7 +1367,9 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
        }
 
        _last_roll_location = _last_roll_or_reversal_location =  _transport_frame;
-       Located (); /* EMIT SIGNAL */
+       if (!synced_to_engine () || _transport_frame == _engine.transport_frame ()) {
+               Located (); /* EMIT SIGNAL */
+       }
 }
 
 /** Set the transport speed.
@@ -1404,6 +1422,7 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a
                                   take care of it.
                                */
                                _play_range = false;
+                               _count_in_once = false;
                                unset_play_loop ();
                        }
                        _engine.transport_stop ();
@@ -1449,6 +1468,7 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a
 
                if (synced_to_engine()) {
                        _engine.transport_start ();
+                       _count_in_once = false;
                } else {
                        start_transport ();
                }
@@ -1541,6 +1561,7 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a
 void
 Session::stop_transport (bool abort, bool clear_state)
 {
+       _count_in_once = false;
        if (_transport_speed == 0.0f) {
                return;
        }
@@ -1674,7 +1695,8 @@ Session::start_transport ()
                        send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
                }
 
-               if (actively_recording() && click_data && config.get_count_in ()) {
+               if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
+                       _count_in_once = false;
                        /* calculate count-in duration (in audio samples)
                         * - use [fixed] tempo/meter at _transport_frame
                         * - calc duration of 1 bar + time-to-beat before or at transport_frame
@@ -1682,19 +1704,20 @@ Session::start_transport ()
                        const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
                        const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
 
-                       double div = meter.divisions_per_bar ();
-                       double pulses = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * div / 4.0;
-                       double beats_left = fmod (pulses, div);
+                       const double num = meter.divisions_per_bar ();
+                       const double den = meter.note_divisor ();
+                       const double barbeat = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * den / (4. * num);
+                       const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
 
                        _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
 
-                       double dt = _count_in_samples / div;
-                       if (beats_left == 0) {
+                       double dt = _count_in_samples / num;
+                       if (bar_fract == 0) {
                                /* at bar boundary, count-in 2 bars before start. */
                                _count_in_samples *= 2;
                        } else {
                                /* beats left after full bar until roll position */
-                               _count_in_samples += meter.frames_per_grid (tempo, _current_frame_rate) * beats_left;
+                               _count_in_samples *= 1. + bar_fract;
                        }
 
                        int clickbeat = 0;
@@ -1702,7 +1725,7 @@ Session::start_transport ()
                        while (cf < _transport_frame) {
                                add_click (cf - _worst_track_latency, clickbeat == 0);
                                cf += dt;
-                               clickbeat = fmod (clickbeat + 1, div);
+                               clickbeat = fmod (clickbeat + 1, num);
                        }
                }
        }
@@ -1735,6 +1758,7 @@ Session::post_transport ()
        if (ptw & PostTransportLocate) {
 
                if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
+                       _count_in_once = false;
                        start_transport ();
                } else {
                        transport_sub_state = 0;