+
+bool
+Session::follow_transport_master (pframes_t nframes)
+{
+ TransportMasterManager& tmm (TransportMasterManager::instance());
+
+ double slave_speed;
+ samplepos_t slave_transport_sample;
+ sampleoffset_t delta;
+
+ if (tmm.master_invalid_this_cycle()) {
+ DEBUG_TRACE (DEBUG::Slave, "session told not to use the transport master this cycle\n");
+ goto noroll;
+ }
+
+ slave_speed = tmm.get_current_speed_in_process_context();
+ slave_transport_sample = tmm.get_current_position_in_process_context ();
+ delta = _transport_sample - slave_transport_sample;
+
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("session at %1, master at %2, delta: %3 res: %4\n", _transport_sample, slave_transport_sample, delta, tmm.current()->resolution()));
+
+ track_transport_master (slave_speed, slave_transport_sample);
+
+ if (transport_master_tracking_state == Running) {
+
+ if (!actively_recording() && abs (delta) > tmm.current()->resolution()) {
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("average slave delta %1 greater than slave resolution %2\n", delta, tmm.current()->resolution()));
+ if (micro_locate (-delta) != 0) {
+ DEBUG_TRACE (DEBUG::Slave, "micro-locate didn't work, set no disk output true\n");
+
+ /* run routes as normal, but no disk output */
+ DiskReader::set_no_disk_output (true);
+ }
+ return true;
+ }
+
+ if (transport_master_tracking_state == Running) {
+ /* speed is set, we're locked, and good to go */
+ DiskReader::set_no_disk_output (false);
+ return true;
+ }
+ }
+
+ noroll:
+ /* don't move at all */
+ DEBUG_TRACE (DEBUG::Slave, "no roll\n")
+ no_roll (nframes);
+ return false;
+}
+
+void
+Session::track_transport_master (float slave_speed, samplepos_t slave_transport_sample)
+{
+ boost::shared_ptr<TransportMaster> master (TransportMasterManager::instance().current());
+
+ assert (master);
+
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("session has master tracking state as %1\n", transport_master_tracking_state));
+
+ if (slave_speed != 0.0f) {
+
+ /* slave is running */
+
+ switch (transport_master_tracking_state) {
+ case Stopped:
+ if (master->requires_seekahead()) {
+ master_wait_end = slave_transport_sample + master->seekahead_distance ();
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", master_wait_end));
+ /* we can call locate() here because we are in process context */
+ if (micro_locate (master_wait_end - _transport_sample) != 0) {
+ locate (master_wait_end, false, false);
+ }
+ transport_master_tracking_state = Waiting;
+
+ } else {
+
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped -> running at %1\n", slave_transport_sample));
+
+ if (slave_transport_sample != _transport_sample) {
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("require locate to run. eng: %1 -> sl: %2\n", _transport_sample, slave_transport_sample));
+ if (micro_locate (slave_transport_sample - _transport_sample) != 0) {
+ locate (slave_transport_sample, false, false);
+ }
+ }
+ transport_master_tracking_state = Running;
+ }
+ break;
+
+ case Waiting:
+ default:
+ break;
+ }
+
+ if (transport_master_tracking_state == Waiting) {
+
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_sample));
+
+ if (slave_transport_sample >= master_wait_end) {
+
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_sample, _transport_sample));
+
+ transport_master_tracking_state = Running;
+
+ /* now perform a "micro-seek" within the disk buffers to realign ourselves
+ precisely with the master.
+ */
+
+ if (micro_locate (slave_transport_sample - _transport_sample) != 0) {
+ cerr << "cannot micro-seek\n";
+ /* XXX what? */
+ }
+ }
+ }
+
+ if (transport_master_tracking_state == Running && _transport_speed == 0.0f) {
+ DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
+ start_transport ();
+ }
+
+ } else { // slave_speed is 0
+
+ /* slave has stopped */
+
+ if (_transport_speed != 0.0f) {
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 sample %2 tf %3\n", slave_speed, slave_transport_sample, _transport_sample));
+ stop_transport ();
+ }
+
+ if (slave_transport_sample != _transport_sample) {
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_sample));
+ force_locate (slave_transport_sample, false);
+ }
+
+ reset_slave_state();
+ }
+}
+
+void
+Session::reset_slave_state ()
+{
+ transport_master_tracking_state = Stopped;
+ DiskReader::set_no_disk_output (false);
+}