Some improvements to performance with crossfades: don't recompute a whole track's...
[ardour.git] / libs / ardour / session_transport.cc
index c8630514616ed414a7684347a050e9e8bc4b50ec..a20856b818700417c5629d50515531bdf2a9d125 100644 (file)
 #include <sigc++/bind.h>
 #include <sigc++/retype.h>
 
-#include <pbd/undo.h>
-#include <pbd/error.h>
+#include "pbd/undo.h"
+#include "pbd/error.h"
 #include <glibmm/thread.h>
-#include <pbd/pthread_utils.h>
-#include <pbd/memento_command.h>
-#include <pbd/stacktrace.h>
+#include "pbd/pthread_utils.h"
+#include "pbd/memento_command.h"
+#include "pbd/stacktrace.h"
 
-#include <midi++/mmc.h>
-#include <midi++/port.h>
+#include "midi++/mmc.h"
+#include "midi++/port.h"
 
-#include <ardour/ardour.h>
-#include <ardour/audioengine.h>
-#include <ardour/session.h>
-#include <ardour/audio_diskstream.h>
-#include <ardour/auditioner.h>
-#include <ardour/slave.h>
-#include <ardour/location.h>
+#include "ardour/ardour.h"
+#include "ardour/audioengine.h"
+#include "ardour/session.h"
+#include "ardour/audio_diskstream.h"
+#include "ardour/auditioner.h"
+#include "ardour/slave.h"
+#include "ardour/location.h"
 
 #include "i18n.h"
 
@@ -74,14 +74,14 @@ Session::request_slave_source (SlaveSource src)
 }
 
 void
-Session::request_transport_speed (float speed)
+Session::request_transport_speed (double speed)
 {
        Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
        queue_event (ev);
 }
 
 void
-Session::request_diskstream_speed (Diskstream& ds, float speed)
+Session::request_diskstream_speed (Diskstream& ds, double speed)
 {
        Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
        ev->set_ptr (&ds);
@@ -176,12 +176,13 @@ Session::realtime_stop (bool abort)
        reset_slave_state ();
 
        _transport_speed = 0;
+       _target_transport_speed = 0;
 
-       if (Config->get_use_video_sync()) {
+       if (config.get_use_video_sync()) {
                waiting_for_sync_offset = true;
        }
 
-       transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0);
+       transport_sub_state = ((Config->get_slave_source() == None && config.get_auto_return()) ? AutoReturning : 0);
 }
 
 void
@@ -342,7 +343,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
 
                        /* stopped recording before current end */
 
-                       if (_end_location_is_free) {
+                       if (config.get_end_marker_is_free()) {
 
                                /* first capture for this session, move end back to where we are */
 
@@ -363,7 +364,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                         add_command (new MementoCommand<Location>(*loc, &before, &after));
                }
 
-               _end_location_is_free = false;
+               config.set_end_marker_is_free (false);
                _have_captured = true;
        }
 
@@ -387,7 +388,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                update_latency_compensation (true, abort);
        }
 
-       if ((Config->get_slave_source() == None && Config->get_auto_return()) ||
+       bool const auto_return_enabled =
+               (Config->get_slave_source() == None && config.get_auto_return());
+       
+       if (auto_return_enabled ||
            (post_transport_work & PostTransportLocate) ||
            (_requested_return_frame >= 0) ||
            synced_to_jack()) {
@@ -396,9 +400,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                        flush_all_inserts ();
                }
 
-               if (((Config->get_slave_source() == None && Config->get_auto_return()) ||
-                    synced_to_jack() ||
-                    _requested_return_frame >= 0) &&
+               if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
                    !(post_transport_work & PostTransportLocate)) {
 
                        bool do_locate = false;
@@ -408,8 +410,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                                _requested_return_frame = -1;
                                do_locate = true;
                        } else {
-                               _transport_frame = last_stop_frame;
-                               _requested_return_frame = -1;
+                               _transport_frame = _last_roll_location;
                        }
 
                        if (synced_to_jack() && !play_loop) {
@@ -441,13 +442,6 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
        }
 #endif
 
-        if (_requested_return_frame < 0) {
-               last_stop_frame = _transport_frame;
-       } else {
-               last_stop_frame = _requested_return_frame;
-               _requested_return_frame = -1;
-       }
-
         have_looped = false; 
 
         send_full_time_code (0);
@@ -628,7 +622,7 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush,
 {
        if (synced_to_jack()) {
 
-               float sp;
+               double sp;
                nframes_t pos;
 
                _slave->speed_and_position (sp, pos);
@@ -648,7 +642,6 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush,
                }
 
        } else {
-
                locate (target_frame, with_roll, with_flush, with_loop);
        }
 }
@@ -706,7 +699,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
                }
        }
 
-       if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
+       if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
                realtime_stop (false);
        }
 
@@ -745,7 +738,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
                        for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
-                                       (*i)->monitor_input (!Config->get_auto_input());
+                                       (*i)->monitor_input (!config.get_auto_input());
                                }
                        }
                }
@@ -792,6 +785,8 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
        loop_changing = false;
 
        _send_smpte_update = true;
+
+       Located (); /* EMIT SIGNAL */
 }
 
 /** Set the transport speed.
@@ -799,16 +794,22 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
  * @param abort
  */
 void
-Session::set_transport_speed (float speed, bool abort)
+Session::set_transport_speed (double speed, bool abort)
 {
        if (_transport_speed == speed) {
                return;
        }
 
+       _target_transport_speed = fabs(speed);
+
+       /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
+          and user needs. We really need CD-style "skip" playback for ffwd and rewind.
+       */
+       
        if (speed > 0) {
-               speed = min (8.0f, speed);
+               speed = min (8.0, speed);
        } else if (speed < 0) {
-               speed = max (-8.0f, speed);
+               speed = max (-8.0, speed);
        }
 
        if (transport_rolling() && speed == 0.0) {
@@ -846,7 +847,7 @@ Session::set_transport_speed (float speed, bool abort)
                        boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
 
                        for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
-                               if (Config->get_auto_input() && (*i)->record_enabled ()) {
+                               if (config.get_auto_input() && (*i)->record_enabled ()) {
                                        //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (false);
                                }
@@ -875,11 +876,11 @@ Session::set_transport_speed (float speed, bool abort)
                        return;
                }
 
-               if (speed > 0.0f && _transport_frame == current_end_frame()) {
+               if (speed > 0.0 && _transport_frame == current_end_frame()) {
                        return;
                }
 
-               if (speed < 0.0f && _transport_frame == 0) {
+               if (speed < 0.0 && _transport_frame == 0) {
                        return;
                }
 
@@ -889,9 +890,8 @@ Session::set_transport_speed (float speed, bool abort)
                   before the last stop, then we have to do extra work.
                */
 
-               if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
+               if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
                        post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
-                       last_stop_frame = _transport_frame;
                }
 
                _last_transport_speed = _transport_speed;
@@ -965,7 +965,7 @@ Session::start_transport ()
 
        switch (record_status()) {
        case Enabled:
-               if (!Config->get_punch_in()) {
+               if (!config.get_punch_in()) {
                        enable_record ();
                }
                break;
@@ -981,7 +981,9 @@ Session::start_transport ()
        }
 
        transport_sub_state |= PendingDeclickIn;
+       
        _transport_speed = 1.0;
+       _target_transport_speed = 1.0;
 
        boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
        for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
@@ -1014,7 +1016,7 @@ Session::post_transport ()
 
        if (post_transport_work & PostTransportLocate) {
 
-               if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
+               if (((Config->get_slave_source() == None && (auto_play_legal && config.get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
                        start_transport ();
 
                } else {
@@ -1088,7 +1090,6 @@ Session::set_slave_source (SlaveSource src)
                        error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
                        return;
                }
-               _desired_transport_speed = _transport_speed;
                break;
 
        case MIDIClock:
@@ -1105,12 +1106,10 @@ Session::set_slave_source (SlaveSource src)
                        error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
                        return;
                }
-               _desired_transport_speed = _transport_speed;
                break;
 
        case JACK:
                _slave = new JACK_Slave (_engine.jack());
-               _desired_transport_speed = _transport_speed;
                break;
 
        };
@@ -1147,7 +1146,7 @@ Session::reverse_diskstream_buffers ()
 }
 
 void
-Session::set_diskstream_speed (Diskstream* stream, float speed)
+Session::set_diskstream_speed (Diskstream* stream, double speed)
 {
        if (stream->realtime_set_speed (speed, false)) {
                post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
@@ -1330,11 +1329,12 @@ Session::update_latency_compensation (bool with_stop, bool abort)
                                                        (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
                }
 
-               nframes_t old_latency = (*i)->signal_latency ();
+               nframes_t old_latency = (*i)->output()->signal_latency ();
                nframes_t track_latency = (*i)->update_total_latency ();
 
                if (old_latency != track_latency) {
-                       (*i)->update_port_total_latencies ();
+                       (*i)->input()->update_port_total_latencies ();
+                       (*i)->output()->update_port_total_latencies ();
                        update_jack = true;
                }