correct problem with some locates that would keep rolling after they are finished
[ardour.git] / libs / ardour / session_transport.cc
1 /*
2  * Copyright (C) 1999-2019 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2005-2009 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2006-2007 Jesse Chappell <jesse@essej.net>
5  * Copyright (C) 2006-2012 David Robillard <d@drobilla.net>
6  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
7  * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
8  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
9  * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
10  * Copyright (C) 2015 GZharun <grygoriiz@wavesglobal.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 #ifdef WAF_BUILD
28 #include "libardour-config.h"
29 #endif
30
31 #include <cmath>
32 #include <cerrno>
33 #include <unistd.h>
34
35 #include <boost/algorithm/string/erase.hpp>
36
37 #include "pbd/error.h"
38 #include "pbd/enumwriter.h"
39 #include "pbd/i18n.h"
40 #include "pbd/memento_command.h"
41 #include "pbd/pthread_utils.h"
42 #include "pbd/stacktrace.h"
43 #include "pbd/undo.h"
44
45 #include "midi++/mmc.h"
46 #include "midi++/port.h"
47
48 #include "ardour/audioengine.h"
49 #include "ardour/auditioner.h"
50 #include "ardour/automation_watch.h"
51 #include "ardour/butler.h"
52 #include "ardour/click.h"
53 #include "ardour/debug.h"
54 #include "ardour/disk_reader.h"
55 #include "ardour/location.h"
56 #include "ardour/playlist.h"
57 #include "ardour/profile.h"
58 #include "ardour/scene_changer.h"
59 #include "ardour/session.h"
60 #include "ardour/transport_fsm.h"
61 #include "ardour/transport_master.h"
62 #include "ardour/transport_master_manager.h"
63 #include "ardour/tempo.h"
64 #include "ardour/operations.h"
65 #include "ardour/vca.h"
66 #include "ardour/vca_manager.h"
67
68 using namespace std;
69 using namespace ARDOUR;
70 using namespace PBD;
71
72
73 #ifdef NDEBUG
74 # define ENSURE_PROCESS_THREAD do {} while (0)
75 #else
76 # define ENSURE_PROCESS_THREAD                           \
77   do {                                                   \
78     if (!AudioEngine::instance()->in_process_thread()) { \
79       PBD::stacktrace (std::cerr, 30);                   \
80     }                                                    \
81   } while (0)
82 #endif
83
84
85 #define TFSM_EVENT(evtype) { _transport_fsm->enqueue (new TransportFSM::Event (evtype)); }
86 #define TFSM_STOP(abort,clear) { _transport_fsm->enqueue (new TransportFSM::Event (TransportFSM::StopTransport,abort,clear)); }
87 #define TFSM_LOCATE(target,roll,flush,loop,force) { _transport_fsm->enqueue (new TransportFSM::Event (TransportFSM::Locate,target,roll,flush,loop,force)); }
88
89 /* *****************************************************************************
90  * REALTIME ACTIONS (to be called on state transitions)
91  * ****************************************************************************/
92
93 void
94 Session::realtime_stop (bool abort, bool clear_state)
95 {
96         ENSURE_PROCESS_THREAD;
97
98         DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1 speed = %2\n", _transport_sample, _transport_speed));
99         PostTransportWork todo = PostTransportWork (0);
100
101         if (_last_transport_speed < 0.0f) {
102                 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
103                 _default_transport_speed = 1.0;
104                 DiskReader::inc_no_disk_output (); // for the buffer reversal
105         } else {
106                 todo = PostTransportWork (todo | PostTransportStop);
107         }
108
109         /* call routes */
110
111         boost::shared_ptr<RouteList> r = routes.reader ();
112
113         for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
114                 (*i)->realtime_handle_transport_stopped ();
115         }
116
117         DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_sample));
118
119         /* the duration change is not guaranteed to have happened, but is likely */
120
121         todo = PostTransportWork (todo | PostTransportDuration);
122
123         if (abort) {
124                 todo = PostTransportWork (todo | PostTransportAbort);
125         }
126
127         if (clear_state) {
128                 todo = PostTransportWork (todo | PostTransportClearSubstate);
129         }
130
131         if (todo) {
132                 add_post_transport_work (todo);
133         }
134
135         _clear_event_type (SessionEvent::RangeStop);
136         _clear_event_type (SessionEvent::RangeLocate);
137
138         //clear our solo-selection, if there is one
139         if ( solo_selection_active() ) {
140                 solo_selection ( _soloSelection, false );
141         }
142
143         /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
144         disable_record (true, (!Config->get_latched_record_enable() && clear_state));
145
146         if (clear_state && !Config->get_loop_is_mode()) {
147                 unset_play_loop ();
148         }
149
150         reset_slave_state ();
151
152         _transport_speed = 0;
153         _target_transport_speed = 0;
154         _engine_speed = 1.0;
155
156         g_atomic_int_set (&_playback_load, 100);
157         g_atomic_int_set (&_capture_load, 100);
158
159         if (config.get_use_video_sync()) {
160                 waiting_for_sync_offset = true;
161         }
162
163         if (todo) {
164                 TFSM_EVENT (TransportFSM::ButlerRequired);
165         }
166 }
167
168 void
169 Session::locate (samplepos_t target_sample, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
170 {
171         ENSURE_PROCESS_THREAD;
172
173         if (target_sample < 0) {
174                 error << _("Locate called for negative sample position - ignored") << endmsg;
175                 return;
176         }
177
178         if (synced_to_engine()) {
179
180                 double sp;
181                 samplepos_t pos;
182                 samplepos_t ignore1, ignore2;
183
184                 transport_master()->speed_and_position (sp, pos, ignore1, ignore2, 0);
185
186                 if (target_sample != pos) {
187
188                         if (config.get_jack_time_master()) {
189                                 /* actually locate now, since otherwise jack_timebase_callback
190                                    will use the incorrect _transport_sample and report an old
191                                    and incorrect time to Jack transport
192                                 */
193                                 do_locate (target_sample, with_roll, with_flush, for_loop_enabled, force, with_mmc);
194                         }
195
196                         /* tell JACK to change transport position, and we will
197                            follow along later in ::follow_slave()
198                         */
199
200                         _engine.transport_locate (target_sample);
201
202                         if (sp != 1.0f && with_roll) {
203                                 _engine.transport_start ();
204                         }
205
206                 }
207
208         } else {
209                 do_locate (target_sample, with_roll, with_flush, for_loop_enabled, force, with_mmc);
210         }
211 }
212
213 /** @param with_mmc true to send a MMC locate command when the locate is done */
214 void
215 Session::do_locate (samplepos_t target_sample, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
216 {
217         ENSURE_PROCESS_THREAD;
218
219         bool need_butler = false;
220
221         /* Locates for seamless looping are fairly different from other
222          * locates. They assume that the diskstream buffers for each track
223          * already have the correct data in them, and thus there is no need to
224          * actually tell the tracks to locate. What does need to be done,
225          * though, is all the housekeeping that is associated with non-linear
226          * changes in the value of _transport_sample.
227          */
228
229         DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
230                                                        target_sample, with_roll, with_flush, for_loop_enabled, force, with_mmc));
231
232         if (!force && _transport_sample == target_sample && !loop_changing && !for_loop_enabled) {
233
234                 /* already at the desired position. Not forced to locate,
235                    the loop isn't changing, so unless we're told to
236                    start rolling also, there's nothing to do but
237                    tell the world where we are (again).
238                 */
239
240                 if (with_roll) {
241                         set_transport_speed (1.0, 0, false);
242                 }
243                 loop_changing = false;
244                 TFSM_EVENT (TransportFSM::LocateDone);
245                 Located (); /* EMIT SIGNAL */
246                 return;
247         }
248
249         // Update Timecode time
250         _transport_sample = target_sample;
251         // Bump seek counter so that any in-process locate in the butler
252         // thread(s?) can restart.
253         g_atomic_int_inc (&_seek_counter);
254         _last_roll_or_reversal_location = target_sample;
255         _remaining_latency_preroll = worst_latency_preroll ();
256         timecode_time(_transport_sample, transmitting_timecode_time); // XXX here?
257
258         /* do "stopped" stuff if:
259          *
260          * we are rolling AND
261          * no autoplay in effect AND
262          * we're not going to keep rolling after the locate AND
263          * !(playing a loop with JACK sync) AND
264          * we're not synced to an external transport master
265          *
266          */
267
268
269         /* it is important here that we use the internal state of the transport
270            FSM, not the public facing result of ::transport_rolling()
271         */
272         bool transport_was_stopped = _transport_fsm->stopped();
273
274         if (!transport_was_stopped &&
275             (!auto_play_legal || !config.get_auto_play()) &&
276             !with_roll &&
277             !(synced_to_engine() && play_loop) &&
278             (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
279
280                 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
281                 transport_was_stopped = true;
282
283         } else {
284
285                 /* Tell all routes to do the RT part of locate */
286
287                 boost::shared_ptr<RouteList> r = routes.reader ();
288                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
289                         (*i)->realtime_locate ();
290                 }
291         }
292
293         if (force || !for_loop_enabled || loop_changing) {
294
295                 PostTransportWork todo = PostTransportLocate;
296
297                 if (with_roll && transport_was_stopped) {
298                         todo = PostTransportWork (todo | PostTransportRoll);
299                 }
300
301                 add_post_transport_work (todo);
302                 need_butler = true;
303
304         } else {
305
306                 /* this is functionally what clear_clicks() does but with a tentative lock */
307
308                 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
309
310                 if (clickm.locked()) {
311
312                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
313                                 delete *i;
314                         }
315
316                         clicks.clear ();
317                 }
318         }
319
320         if (with_roll) {
321                 /* switch from input if we're going to roll */
322                 if (Config->get_monitoring_model() == HardwareMonitoring) {
323                         set_track_monitor_input_status (!config.get_auto_input());
324                 }
325         } else {
326                 /* otherwise we're going to stop, so do the opposite */
327                 if (Config->get_monitoring_model() == HardwareMonitoring) {
328                         set_track_monitor_input_status (true);
329                 }
330         }
331
332         /* cancel looped playback if transport pos outside of loop range */
333         if (play_loop) {
334
335                 Location* al = _locations->auto_loop_location();
336
337                 if (al) {
338                         if (_transport_sample < al->start() || _transport_sample >= al->end()) {
339
340                                 // located outside the loop: cancel looping directly, this is called from event handling context
341
342                                 have_looped = false;
343
344                                 if (!Config->get_loop_is_mode()) {
345                                         set_play_loop (false, _transport_speed);
346                                 } else {
347                                         if (Config->get_seamless_loop()) {
348                                                 /* this will make the non_realtime_locate() in the butler
349                                                    which then causes seek() in tracks actually do the right
350                                                    thing.
351                                                 */
352                                                 set_track_loop (false);
353                                         }
354                                 }
355
356                         } else if (_transport_sample == al->start()) {
357
358                                 // located to start of loop - this is looping, basically
359
360                                 if (!have_looped) {
361                                         /* first time */
362                                         if (_last_roll_location != al->start()) {
363                                                 /* didn't start at loop start - playback must have
364                                                  * started before loop since we've now hit the loop
365                                                  * end.
366                                                  */
367                                                 add_post_transport_work (PostTransportLocate);
368                                                 need_butler = true;
369                                         }
370
371                                 }
372
373                                 boost::shared_ptr<RouteList> rl = routes.reader();
374
375                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
376                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
377
378                                         if (tr && tr->rec_enable_control()->get_value()) {
379                                                 // tell it we've looped, so it can deal with the record state
380                                                 tr->transport_looped (_transport_sample);
381                                         }
382                                 }
383
384                                 have_looped = true;
385                                 TransportLooped(); // EMIT SIGNAL
386                         }
387                 }
388         }
389
390         if (need_butler) {
391                 TFSM_EVENT (TransportFSM::ButlerRequired);
392         } else {
393                 TFSM_EVENT (TransportFSM::LocateDone);
394         }
395
396         loop_changing = false;
397
398         _send_timecode_update = true;
399
400         if (with_mmc) {
401                 send_mmc_locate (_transport_sample);
402         }
403
404         _last_roll_location = _last_roll_or_reversal_location =  _transport_sample;
405         if (!synced_to_engine () || _transport_sample == _engine.transport_sample ()) {
406                 Located (); /* EMIT SIGNAL */
407         }
408 }
409
410 void
411 Session::post_locate ()
412 {
413         if (transport_master_is_external() && !synced_to_engine()) {
414                 const samplepos_t current_master_position = TransportMasterManager::instance().get_current_position_in_process_context();
415                 if (abs (current_master_position - _transport_sample) > TransportMasterManager::instance().current()->resolution()) {
416                         _last_roll_location = _last_roll_or_reversal_location =  _transport_sample;
417                 }
418         }
419 }
420
421 /** Set the transport speed.
422  *  Called from the process thread.
423  *  @param speed New speed
424  */
425 void
426 Session::set_transport_speed (double speed, samplepos_t destination_sample, bool abort, bool clear_state, bool as_default)
427 {
428         ENSURE_PROCESS_THREAD;
429         DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
430                                                        speed, abort, clear_state, _transport_speed, _transport_sample, as_default));
431
432         /* max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
433            and user needs. We really need CD-style "skip" playback for ffwd and rewind.
434         */
435
436         if (speed > 0) {
437                 speed = min ((double) Config->get_max_transport_speed(), speed);
438         } else if (speed < 0) {
439                 speed = max ((double) -Config->get_max_transport_speed(), speed);
440         }
441
442         double new_engine_speed = 1.0;
443         if (speed != 0) {
444                 new_engine_speed = fabs (speed);
445                 if (speed < 0) speed = -1;
446                 if (speed > 0) speed = 1;
447         }
448
449         if (_transport_speed == speed && new_engine_speed == _engine_speed) {
450                 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
451                         _default_transport_speed = 1.0;
452                 }
453                 return;
454         }
455
456 #if 0 // TODO pref: allow vari-speed recording
457         if (actively_recording() && speed != 1.0 && speed != 0.0) {
458                 /* no varispeed during recording */
459                 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, sample %2\n",
460                                                        _transport_speed, _transport_sample));
461                 return;
462         }
463 #endif
464
465         _target_transport_speed = fabs(speed);
466         _engine_speed = new_engine_speed;
467
468         if (transport_rolling() && speed == 0.0) {
469
470                 /* we are rolling and we want to stop */
471
472                 if (Config->get_monitoring_model() == HardwareMonitoring) {
473                         set_track_monitor_input_status (true);
474                 }
475
476                 if (synced_to_engine ()) {
477                         if (clear_state) {
478                                 /* do this here because our response to the slave won't
479                                    take care of it.
480                                 */
481                                 _play_range = false;
482                                 _count_in_once = false;
483                                 unset_play_loop ();
484                         }
485                         _engine.transport_stop ();
486                 } else {
487                         bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
488
489                         if (!auto_return_enabled) {
490                                 _requested_return_sample = destination_sample;
491                         }
492
493                         TFSM_STOP (abort, false);
494                 }
495
496         } else if (transport_stopped() && speed == 1.0) {
497                 if (as_default) {
498                         _default_transport_speed = speed;
499                 }
500                 /* we are stopped and we want to start rolling at speed 1 */
501
502                 if (Config->get_loop_is_mode() && play_loop) {
503
504                         Location *location = _locations->auto_loop_location();
505
506                         if (location != 0) {
507                                 if (_transport_sample != location->start()) {
508
509                                         if (Config->get_seamless_loop()) {
510                                                 /* force tracks to do their thing */
511                                                 set_track_loop (true);
512                                         }
513
514                                         /* jump to start and then roll from there */
515
516                                         request_locate (location->start(), true);
517                                         return;
518                                 }
519                         }
520                 }
521
522                 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
523                         set_track_monitor_input_status (false);
524                 }
525
526                 if (synced_to_engine()) {
527                         _engine.transport_start ();
528                         _count_in_once = false;
529                 } else {
530                         TFSM_EVENT (TransportFSM::StartTransport);
531                 }
532
533         } else {
534
535                 /* not zero, not 1.0 ... varispeed */
536
537                 // TODO handled transport start..  _remaining_latency_preroll
538                 // and reversal of playback direction.
539
540                 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
541                         warning << string_compose (
542                                 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
543                                 PROGRAM_NAME)
544                                 << endmsg;
545                         return;
546                 }
547
548 #if 0
549                 if (actively_recording()) {
550                         return;
551                 }
552 #endif
553
554                 if (speed > 0.0 && _transport_sample == current_end_sample()) {
555                         return;
556                 }
557
558                 if (speed < 0.0 && _transport_sample == 0) {
559                         return;
560                 }
561
562                 clear_clicks ();
563
564                 /* if we are reversing relative to the current speed, or relative to the speed
565                    before the last stop, then we have to do extra work.
566                 */
567
568                 PostTransportWork todo = PostTransportWork (0);
569
570                 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
571                         todo = PostTransportWork (todo | PostTransportReverse);
572                         DiskReader::inc_no_disk_output (); // for the buffer reversal
573                         _last_roll_or_reversal_location = _transport_sample;
574                 }
575
576                 _last_transport_speed = _transport_speed;
577                 _transport_speed = speed;
578
579                 if (as_default) {
580                         _default_transport_speed = speed;
581                 }
582
583                 if (todo) {
584                         add_post_transport_work (todo);
585                         TFSM_EVENT (TransportFSM::ButlerRequired);
586                 }
587
588                 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
589
590                 /* throttle signal emissions.
591                  * when slaved [_last]_transport_speed
592                  * usually changes every cycle (tiny amounts due to DLL).
593                  * Emitting a signal every cycle is overkill and unwarranted.
594                  *
595                  * Using _last_transport_speed is not acceptable,
596                  * since it allows for large changes over a long period
597                  * of time. Hence we introduce a dedicated variable to keep track
598                  *
599                  * The 0.2% dead-zone is somewhat arbitrary. Main use-case
600                  * for TransportStateChange() here is the ShuttleControl display.
601                  */
602                 if (fabs (_signalled_varispeed - actual_speed ()) > .002
603                     // still, signal hard changes to 1.0 and 0.0:
604                     || (actual_speed () == 1.0 && _signalled_varispeed != 1.0)
605                     || (actual_speed () == 0.0 && _signalled_varispeed != 0.0)
606                    )
607                 {
608                         TransportStateChange (); /* EMIT SIGNAL */
609                         _signalled_varispeed = actual_speed ();
610                 }
611         }
612 }
613
614 /** Stop the transport.  */
615 void
616 Session::stop_transport (bool abort, bool clear_state)
617 {
618         ENSURE_PROCESS_THREAD;
619
620         _count_in_once = false;
621
622         DEBUG_TRACE (DEBUG::Transport, string_compose ("time to actually stop with TS @ %1\n", _transport_sample));
623
624         realtime_stop (abort, clear_state);
625 }
626
627 /** Called from the process thread */
628 void
629 Session::start_transport ()
630 {
631         ENSURE_PROCESS_THREAD;
632         DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
633
634         _last_roll_location = _transport_sample;
635         _last_roll_or_reversal_location = _transport_sample;
636         _remaining_latency_preroll = worst_latency_preroll ();
637
638         have_looped = false;
639
640         /* if record status is Enabled, move it to Recording. if its
641            already Recording, move it to Disabled.
642         */
643
644         switch (record_status()) {
645         case Enabled:
646                 if (!config.get_punch_in()) {
647                         /* This is only for UIs (keep blinking rec-en before
648                          * punch-in, don't show rec-region etc). The UI still
649                          * depends on SessionEvent::PunchIn and ensuing signals.
650                          *
651                          * The disk-writers handle punch in/out internally
652                          * in their local delay-compensated timeframe.
653                          */
654                         enable_record ();
655                 }
656                 break;
657
658         case Recording:
659                 if (!play_loop) {
660                         disable_record (false);
661                 }
662                 break;
663
664         default:
665                 break;
666         }
667
668         _transport_speed = _default_transport_speed;
669         _target_transport_speed = _transport_speed;
670
671         if (!_engine.freewheeling()) {
672                 Timecode::Time time;
673                 timecode_time_subframes (_transport_sample, time);
674                 if (transport_master()->type() == MTC) {
675                         send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
676                 }
677
678                 if ((actively_recording () || (config.get_punch_in () && get_record_enabled ()))
679                     && click_data && (config.get_count_in () || _count_in_once)) {
680                         _count_in_once = false;
681                         /* calculate count-in duration (in audio samples)
682                          * - use [fixed] tempo/meter at _transport_sample
683                          * - calc duration of 1 bar + time-to-beat before or at transport_sample
684                          */
685                         const Tempo& tempo = _tempo_map->tempo_at_sample (_transport_sample);
686                         const Meter& meter = _tempo_map->meter_at_sample (_transport_sample);
687
688                         const double num = meter.divisions_per_bar ();
689                         const double den = meter.note_divisor ();
690                         const double barbeat = _tempo_map->exact_qn_at_sample (_transport_sample, 0) * den / (4. * num);
691                         const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
692
693                         _count_in_samples = meter.samples_per_bar (tempo, _current_sample_rate);
694
695                         double dt = _count_in_samples / num;
696                         if (bar_fract == 0) {
697                                 /* at bar boundary, count-in 2 bars before start. */
698                                 _count_in_samples *= 2;
699                         } else {
700                                 /* beats left after full bar until roll position */
701                                 _count_in_samples *= 1. + bar_fract;
702                         }
703
704                         if (_count_in_samples > _remaining_latency_preroll) {
705                                 _remaining_latency_preroll = _count_in_samples;
706                         }
707
708                         int clickbeat = 0;
709                         samplepos_t cf = _transport_sample - _count_in_samples;
710                         samplecnt_t offset = _click_io->connected_latency (true);
711                         while (cf < _transport_sample + offset) {
712                                 add_click (cf, clickbeat == 0);
713                                 cf += dt;
714                                 clickbeat = fmod (clickbeat + 1, num);
715                         }
716
717                         if (_count_in_samples < _remaining_latency_preroll) {
718                                 _count_in_samples = _remaining_latency_preroll;
719                         }
720                 }
721         }
722
723         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
724         TransportStateChange (); /* EMIT SIGNAL */
725 }
726
727 bool
728 Session::should_roll_after_locate () const
729 {
730         /* a locate must previously have been requested and completed */
731
732         return ((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (post_transport_work() & PostTransportRoll);
733
734 }
735
736 /** Do any transport work in the audio thread that needs to be done after the
737  * butler thread is finished.  Audio thread, realtime safe.
738  */
739 void
740 Session::butler_completed_transport_work ()
741 {
742         ENSURE_PROCESS_THREAD;
743         PostTransportWork ptw = post_transport_work ();
744
745         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler done, RT cleanup for %1\n", enum_2_string (ptw)));
746
747         if (ptw & PostTransportAudition) {
748                 if (auditioner && auditioner->auditioning()) {
749                         process_function = &Session::process_audition;
750                 } else {
751                         process_function = &Session::process_with_events;
752                 }
753         }
754
755         if (ptw & PostTransportLocate) {
756                 post_locate ();
757                 TFSM_EVENT (TransportFSM::LocateDone);
758         }
759
760         if (ptw & PostTransportAdjustPlaybackBuffering) {
761                 /* we blocked output while this happened */
762                 DiskReader::dec_no_disk_output ();
763         }
764
765         set_next_event ();
766         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
767            know were handled ?
768         */
769         set_post_transport_work (PostTransportWork (0));
770
771         if (_transport_fsm->waiting_for_butler()) {
772                 TFSM_EVENT (TransportFSM::ButlerDone);
773         }
774
775         DiskReader::dec_no_disk_output ();
776 }
777
778 void
779 Session::schedule_butler_for_transport_work ()
780 {
781         assert (_transport_fsm->waiting_for_butler ());
782         DEBUG_TRACE (DEBUG::Butler, "summon butler for transport work\n");
783         _butler->schedule_transport_work ();
784 }
785
786 bool
787 Session::maybe_stop (samplepos_t limit)
788 {
789         ENSURE_PROCESS_THREAD;
790         if ((_transport_speed > 0.0f && _transport_sample >= limit) || (_transport_speed < 0.0f && _transport_sample == 0)) {
791                 if (synced_to_engine () && config.get_jack_time_master ()) {
792                         _engine.transport_stop ();
793                 } else if (!synced_to_engine ()) {
794                         TFSM_EVENT (TransportFSM::StopTransport);
795                 }
796                 return true;
797         }
798         return false;
799 }
800
801 int
802 Session::micro_locate (samplecnt_t distance)
803 {
804         ENSURE_PROCESS_THREAD;
805
806         boost::shared_ptr<RouteList> rl = routes.reader();
807         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
808                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
809                 if (tr && !tr->can_internal_playback_seek (distance)) {
810                         return -1;
811                 }
812         }
813
814         DEBUG_TRACE (DEBUG::Transport, string_compose ("micro-locate by %1\n", distance));
815
816         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
817                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
818                 if (tr) {
819                         tr->internal_playback_seek (distance);
820                 }
821         }
822
823         _transport_sample += distance;
824         return 0;
825 }
826
827 void
828 Session::flush_all_inserts ()
829 {
830         ENSURE_PROCESS_THREAD;
831         boost::shared_ptr<RouteList> r = routes.reader ();
832
833         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
834                 (*i)->flush_processors ();
835         }
836 }
837
838 void
839 Session::set_play_loop (bool yn, double speed)
840 {
841         ENSURE_PROCESS_THREAD;
842         /* Called from event-handling context */
843
844         Location *loc;
845
846         if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
847                 /* nothing to do, or can't change loop status while recording */
848                 return;
849         }
850
851         if (yn && Config->get_seamless_loop() && synced_to_engine()) {
852                 warning << string_compose (
853                         _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
854                           "Recommend changing the configured options"), PROGRAM_NAME)
855                         << endmsg;
856                 return;
857         }
858
859         if (yn) {
860
861                 play_loop = true;
862                 have_looped = false;
863
864                 if (loc) {
865
866                         unset_play_range ();
867
868                         if (Config->get_seamless_loop()) {
869                                 if (!Config->get_loop_is_mode()) {
870                                         /* set all tracks to use internal looping */
871                                         set_track_loop (true);
872                                 } else {
873                                         /* we will do this in the locate to the start OR when we hit the end
874                                          * of the loop for the first time
875                                          */
876                                 }
877                         } else {
878                                 /* set all tracks to NOT use internal looping */
879                                 set_track_loop (false);
880                         }
881
882                         /* Put the delick and loop events in into the event list.  The declick event will
883                            cause a de-clicking fade-out just before the end of the loop, and it will also result
884                            in a fade-in when the loop restarts.  The AutoLoop event will peform the actual loop.
885                         */
886
887                         samplepos_t dcp;
888                         samplecnt_t dcl;
889                         auto_loop_declick_range (loc, dcp, dcl);
890                         merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
891
892                         /* if requested to roll, locate to start of loop and
893                          * roll but ONLY if we're not already rolling.
894
895                            args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
896                         */
897
898                         if (Config->get_loop_is_mode()) {
899                                 /* loop IS a transport mode: if already
900                                    rolling, do not locate to loop start.
901                                 */
902                                 if (!transport_rolling() && (speed != 0.0)) {
903                                         TFSM_LOCATE (loc->start(), true, true, false, true);
904                                 }
905                         } else {
906                                 if (speed != 0.0) {
907                                         TFSM_LOCATE (loc->start(), true, true, false, true);
908                                 }
909                         }
910                 }
911
912         } else {
913
914                 unset_play_loop ();
915         }
916
917         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
918         TransportStateChange ();
919 }
920
921 /* *****************************************************************************
922  * END REALTIME ACTIONS
923  * ****************************************************************************/
924
925
926 void
927 Session::add_post_transport_work (PostTransportWork ptw)
928 {
929         PostTransportWork oldval;
930         PostTransportWork newval;
931         int tries = 0;
932
933         while (tries < 8) {
934                 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
935                 newval = PostTransportWork (oldval | ptw);
936                 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
937                         /* success */
938                         return;
939                 }
940         }
941
942         error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
943 }
944
945 bool
946 Session::should_ignore_transport_request (TransportRequestSource src, TransportRequestType type) const
947 {
948         if (config.get_external_sync()) {
949                 if (TransportMasterManager::instance().current()->allow_request (src, type)) {
950                         return false;
951                 } else {
952                         return true;
953                 }
954         }
955         return false;
956 }
957
958 bool
959 Session::synced_to_engine() const {
960         return config.get_external_sync() && TransportMasterManager::instance().current()->type() == Engine;
961 }
962
963 void
964 Session::request_sync_source (boost::shared_ptr<TransportMaster> tm)
965 {
966         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportMaster, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
967         ev->transport_master = tm;
968         DEBUG_TRACE (DEBUG::Slave, "sent request for new transport master\n");
969         queue_event (ev);
970 }
971
972 void
973 Session::request_transport_speed (double speed, bool as_default, TransportRequestSource origin)
974 {
975         if (should_ignore_transport_request (origin, TR_Speed)) {
976                 return;
977         }
978         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
979         ev->third_yes_or_no = as_default; // as_default
980         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
981         queue_event (ev);
982 }
983
984 /** Request a new transport speed, but if the speed parameter is exactly zero then use
985  *  a very small +ve value to prevent the transport actually stopping.  This method should
986  *  be used by callers who are varying transport speed but don't ever want to stop it.
987  */
988 void
989 Session::request_transport_speed_nonzero (double speed, bool as_default, TransportRequestSource origin)
990 {
991         if (should_ignore_transport_request (origin, TransportRequestType (TR_Speed|TR_Start))) {
992                 return;
993         }
994
995         if (speed == 0) {
996                 speed = DBL_EPSILON;
997         }
998
999         request_transport_speed (speed, as_default);
1000 }
1001
1002 void
1003 Session::request_stop (bool abort, bool clear_state, TransportRequestSource origin)
1004 {
1005         if (should_ignore_transport_request (origin, TR_Stop)) {
1006                 return;
1007         }
1008
1009         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_sample(), 0.0, abort, clear_state);
1010         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, audible %3 transport %4 abort = %1, clear state = %2\n", abort, clear_state, audible_sample(), _transport_sample));
1011         queue_event (ev);
1012 }
1013
1014 void
1015 Session::request_locate (samplepos_t target_sample, bool with_roll, TransportRequestSource origin)
1016 {
1017         if (should_ignore_transport_request (origin, TR_Locate)) {
1018                 return;
1019         }
1020
1021         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_sample, 0, false);
1022         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_sample));
1023         queue_event (ev);
1024 }
1025
1026 void
1027 Session::force_locate (samplepos_t target_sample, bool with_roll)
1028 {
1029         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_sample, 0, true);
1030         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_sample));
1031         queue_event (ev);
1032 }
1033
1034 void
1035 Session::unset_preroll_record_trim ()
1036 {
1037         _preroll_record_trim_len = 0;
1038 }
1039
1040 void
1041 Session::request_preroll_record_trim (samplepos_t rec_in, samplecnt_t preroll)
1042 {
1043         if (actively_recording ()) {
1044                 return;
1045         }
1046         unset_preroll_record_trim ();
1047
1048         config.set_punch_in (false);
1049         config.set_punch_out (false);
1050
1051         samplepos_t pos = std::max ((samplepos_t)0, rec_in - preroll);
1052         _preroll_record_trim_len = preroll;
1053         maybe_enable_record ();
1054         request_locate (pos, true);
1055         set_requested_return_sample (rec_in);
1056 }
1057
1058 void
1059 Session::request_count_in_record ()
1060 {
1061         if (actively_recording ()) {
1062                 return;
1063         }
1064         if (transport_rolling()) {
1065                 return;
1066         }
1067         maybe_enable_record ();
1068         _count_in_once = true;
1069         request_transport_speed (1.0, true);
1070 }
1071
1072 void
1073 Session::request_play_loop (bool yn, bool change_transport_roll)
1074 {
1075         if (transport_master_is_external() && yn) {
1076                 // don't attempt to loop when not using Internal Transport
1077                 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
1078                 return;
1079         }
1080
1081         SessionEvent* ev;
1082         Location *location = _locations->auto_loop_location();
1083         double target_speed;
1084
1085         if (location == 0 && yn) {
1086                 error << _("Cannot loop - no loop range defined")
1087                       << endmsg;
1088                 return;
1089         }
1090
1091         if (change_transport_roll) {
1092                 if (transport_rolling()) {
1093                         /* start looping at current speed */
1094                         target_speed = transport_speed ();
1095                 } else {
1096                         /* currently stopped */
1097                         if (yn) {
1098                                 /* start looping at normal speed */
1099                                 target_speed = 1.0;
1100                         } else {
1101                                 target_speed = 0.0;
1102                         }
1103                 }
1104         } else {
1105                 /* leave the speed alone */
1106                 target_speed = transport_speed ();
1107         }
1108
1109         ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
1110         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
1111         queue_event (ev);
1112
1113         if (yn) {
1114                 if (!change_transport_roll) {
1115                         if (!transport_rolling()) {
1116                                 /* we're not changing transport state, but we do want
1117                                    to set up position for the new loop. Don't
1118                                    do this if we're rolling already.
1119                                 */
1120                                 request_locate (location->start(), false);
1121                         }
1122                 }
1123         } else {
1124                 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
1125                         // request an immediate locate to refresh the tracks
1126                         // after disabling looping
1127                         request_locate (_transport_sample-1, false);
1128                 }
1129         }
1130 }
1131
1132 void
1133 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
1134 {
1135         SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
1136         if (range) {
1137                 ev->audio_range = *range;
1138         } else {
1139                 ev->audio_range.clear ();
1140         }
1141         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
1142         queue_event (ev);
1143 }
1144
1145 void
1146 Session::request_cancel_play_range ()
1147 {
1148         SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
1149         queue_event (ev);
1150 }
1151
1152
1153 bool
1154 Session::solo_selection_active ()
1155 {
1156         if (_soloSelection.empty()) {
1157                 return false;
1158         }
1159         return true;
1160 }
1161
1162 void
1163 Session::solo_selection (StripableList &list, bool new_state)
1164 {
1165         boost::shared_ptr<ControlList> solo_list (new ControlList);
1166         boost::shared_ptr<ControlList> unsolo_list (new ControlList);
1167
1168         if (new_state)
1169                 _soloSelection = list;
1170         else
1171                 _soloSelection.clear();
1172
1173         boost::shared_ptr<RouteList> rl = get_routes();
1174
1175         for (ARDOUR::RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1176
1177                 if ( !(*i)->is_track() ) {
1178                         continue;
1179                 }
1180
1181                 boost::shared_ptr<Stripable> s (*i);
1182
1183                 bool found = (std::find(list.begin(), list.end(), s) != list.end());
1184                 if ( new_state && found ) {
1185
1186                         solo_list->push_back (s->solo_control());
1187
1188                         //must invalidate playlists on selected tracks, so only selected regions get heard
1189                         boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (*i);
1190                         if (track) {
1191                                 boost::shared_ptr<Playlist> playlist = track->playlist();
1192                                 if (playlist) {
1193                                         playlist->ContentsChanged();
1194                                 }
1195                         }
1196                 } else {
1197                         unsolo_list->push_back (s->solo_control());
1198                 }
1199         }
1200
1201         set_controls (solo_list, 1.0, Controllable::NoGroup);
1202         set_controls (unsolo_list, 0.0, Controllable::NoGroup);
1203 }
1204
1205
1206 void
1207 Session::butler_transport_work ()
1208 {
1209         /* Note: this function executes in the butler thread context */
1210
1211   restart:
1212         boost::shared_ptr<RouteList> r = routes.reader ();
1213         int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
1214         bool finished = true;
1215         PostTransportWork ptw = post_transport_work();
1216         uint64_t before;
1217
1218         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = [%1] (0x%3%4%5) at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time()), std::hex, ptw, std::dec));
1219
1220         if (ptw & PostTransportLocate) {
1221
1222                 if (get_play_loop() && !Config->get_seamless_loop()) {
1223
1224                         DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
1225
1226                         /* this locate might be happening while we are
1227                          * loop recording.
1228                          *
1229                          * Non-seamless looping will require a locate (below) that
1230                          * will reset capture buffers and throw away data.
1231                          *
1232                          * Rather than first find all tracks and see if they
1233                          * have outstanding data, just do a flush anyway. It
1234                          * may be cheaper this way anyway, and is certainly
1235                          * more accurate.
1236                          */
1237
1238                         bool more_disk_io_to_do = false;
1239                         uint32_t errors = 0;
1240
1241                         do {
1242                                 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
1243
1244                                 if (errors) {
1245                                         break;
1246                                 }
1247
1248                                 if (more_disk_io_to_do) {
1249                                         continue;
1250                                 }
1251
1252                         } while (false);
1253
1254                 }
1255         }
1256
1257         if (ptw & PostTransportAdjustPlaybackBuffering) {
1258                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1259                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1260                         if (tr) {
1261                                 tr->adjust_playback_buffering ();
1262                                 /* and refill those buffers ... */
1263                         }
1264                         (*i)->non_realtime_locate (_transport_sample);
1265                 }
1266                 VCAList v = _vca_manager->vcas ();
1267                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1268                         (*i)->non_realtime_locate (_transport_sample);
1269                 }
1270         }
1271
1272         if (ptw & PostTransportAdjustCaptureBuffering) {
1273                 /* need to prevent concurrency with ARDOUR::DiskWriter::run(),
1274                  * DiskWriter::adjust_buffering() re-allocates the ringbuffer */
1275                 Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
1276                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1277                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1278                         if (tr) {
1279                                 tr->adjust_capture_buffering ();
1280                         }
1281                 }
1282         }
1283
1284         if (ptw & PostTransportReverse) {
1285
1286                 clear_clicks();
1287
1288                 /* don't seek if locate will take care of that in non_realtime_stop() */
1289
1290                 if (!(ptw & PostTransportLocate)) {
1291                         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1292                                 (*i)->non_realtime_locate (_transport_sample);
1293
1294                                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1295                                         /* new request, stop seeking, and start again */
1296                                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1297                                         goto restart;
1298                                 }
1299                         }
1300                         VCAList v = _vca_manager->vcas ();
1301                         for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1302                                 (*i)->non_realtime_locate (_transport_sample);
1303                         }
1304                 }
1305         }
1306
1307         if (ptw & PostTransportLocate) {
1308                 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
1309                 non_realtime_locate ();
1310         }
1311
1312         if (ptw & PostTransportStop) {
1313                 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
1314                 if (!finished) {
1315                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1316                         goto restart;
1317                 }
1318         }
1319
1320         if (ptw & PostTransportOverWrite) {
1321                 non_realtime_overwrite (on_entry, finished);
1322                 if (!finished) {
1323                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1324                         goto restart;
1325                 }
1326         }
1327
1328         if (ptw & PostTransportAudition) {
1329                 non_realtime_set_audition ();
1330         }
1331
1332         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1333
1334         DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs @ %2 trw = %3\n"), g_get_monotonic_time() - before, _transport_sample, _butler->transport_work_requested()));
1335 }
1336
1337 void
1338 Session::non_realtime_overwrite (int on_entry, bool& finished)
1339 {
1340         boost::shared_ptr<RouteList> rl = routes.reader();
1341         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1342                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1343                 if (tr && tr->pending_overwrite ()) {
1344                         tr->overwrite_existing_buffers ();
1345                 }
1346                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1347                         finished = false;
1348                         return;
1349                 }
1350         }
1351 }
1352
1353 void
1354 Session::non_realtime_locate ()
1355 {
1356         DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_sample));
1357
1358         if (Config->get_loop_is_mode() && get_play_loop()) {
1359
1360                 Location *loc  = _locations->auto_loop_location();
1361
1362                 if (!loc || (_transport_sample < loc->start() || _transport_sample >= loc->end())) {
1363                         /* jumped out of loop range: stop tracks from looping,
1364                            but leave loop (mode) enabled.
1365                          */
1366                         set_track_loop (false);
1367
1368                 } else if (loc && Config->get_seamless_loop() &&
1369                            ((loc->start() <= _transport_sample) || (loc->end() > _transport_sample))) {
1370
1371                         /* jumping to start of loop. This  might have been done before but it is
1372                          * idempotent and cheap. Doing it here ensures that when we start playback
1373                          * outside the loop we still flip tracks into the magic seamless mode
1374                          * when needed.
1375                          */
1376                         set_track_loop (true);
1377
1378                 } else if (loc) {
1379                         set_track_loop (false);
1380                 }
1381
1382         } else {
1383
1384                 /* no more looping .. should have been noticed elsewhere */
1385         }
1386
1387
1388         samplepos_t tf;
1389
1390         {
1391                 boost::shared_ptr<RouteList> rl = routes.reader();
1392
1393           restart:
1394                 gint sc = g_atomic_int_get (&_seek_counter);
1395                 tf = _transport_sample;
1396
1397                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1398                         (*i)->non_realtime_locate (tf);
1399                         if (sc != g_atomic_int_get (&_seek_counter)) {
1400                                 std::cerr << "\n\nLOCATE INTERRUPTED BY LOCATE!!!\n\n";
1401                                 goto restart;
1402                         }
1403                 }
1404         }
1405
1406         {
1407                 /* VCAs are quick to locate because they have no data (except
1408                    automation) associated with them. Don't bother with a
1409                    restart mechanism here, but do use the same transport sample
1410                    that the Routes used.
1411                 */
1412                 VCAList v = _vca_manager->vcas ();
1413                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1414                         (*i)->non_realtime_locate (tf);
1415                 }
1416         }
1417
1418         _scene_changer->locate (_transport_sample);
1419
1420         /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
1421            rather than clearing them so that the RT thread has to spend time constructing
1422            them (in Session::click).
1423          */
1424         clear_clicks ();
1425 }
1426
1427 #ifdef USE_TRACKS_CODE_FEATURES
1428 bool
1429 Session::select_playhead_priority_target (samplepos_t& jump_to)
1430 {
1431         jump_to = -1;
1432
1433         AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
1434
1435         if (!autoreturn) {
1436                 return false;
1437         }
1438
1439         if (Profile->get_trx() && transport_rolling() ) {
1440                 // We're playing, so do nothing.
1441                 // Next stop will put us where we need to be.
1442                 return false;
1443         }
1444
1445         /* Note that the order of checking each AutoReturnTarget flag defines
1446            the priority each flag.
1447
1448            Ardour/Mixbus: Last Locate
1449                           Range Selection
1450                           Loop Range
1451                           Region Selection
1452
1453            Tracks:        Range Selection
1454                           Loop Range
1455                           Region Selection
1456                           Last Locate
1457         */
1458
1459         if (autoreturn & RangeSelectionStart) {
1460                 if (!_range_selection.empty()) {
1461                         jump_to = _range_selection.from;
1462                 } else {
1463                         if (transport_rolling ()) {
1464                                 /* Range selection no longer exists, but we're playing,
1465                                    so do nothing. Next stop will put us where
1466                                    we need to be.
1467                                 */
1468                                 return false;
1469                         }
1470                 }
1471         }
1472
1473         if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
1474                 /* don't try to handle loop play when synced to JACK */
1475
1476                 if (!synced_to_engine()) {
1477                         Location *location = _locations->auto_loop_location();
1478
1479                         if (location) {
1480                                 jump_to = location->start();
1481
1482                                 if (Config->get_seamless_loop()) {
1483                                         /* need to get track buffers reloaded */
1484                                         set_track_loop (true);
1485                                 }
1486                         }
1487                 }
1488         }
1489
1490         if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
1491                 if (!_object_selection.empty()) {
1492                         jump_to = _object_selection.from;
1493                 }
1494         }
1495
1496         if (jump_to < 0 && (autoreturn & LastLocate)) {
1497                 jump_to = _last_roll_location;
1498         }
1499
1500         return jump_to >= 0;
1501 }
1502 #else
1503
1504 bool
1505 Session::select_playhead_priority_target (samplepos_t& jump_to)
1506 {
1507         if (!transport_master_no_external_or_using_engine() || !config.get_auto_return()) {
1508                 return false;
1509         }
1510
1511         jump_to = _last_roll_location;
1512         return jump_to >= 0;
1513 }
1514
1515 #endif
1516
1517 void
1518 Session::follow_playhead_priority ()
1519 {
1520         samplepos_t target;
1521
1522         if (select_playhead_priority_target (target)) {
1523                 request_locate (target);
1524         }
1525 }
1526
1527 void
1528 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
1529 {
1530         struct tm* now;
1531         time_t     xnow;
1532         bool       did_record;
1533         bool       saved;
1534         PostTransportWork ptw = post_transport_work();
1535
1536         did_record = false;
1537         saved = false;
1538
1539         boost::shared_ptr<RouteList> rl = routes.reader();
1540         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1541                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1542                 if (tr && tr->get_captured_samples () != 0) {
1543                         did_record = true;
1544                         break;
1545                 }
1546         }
1547
1548         /* stop and locate are merged here because they share a lot of common stuff */
1549
1550         time (&xnow);
1551         now = localtime (&xnow);
1552
1553         if (auditioner) {
1554                 auditioner->cancel_audition ();
1555         }
1556
1557         if (did_record) {
1558                 begin_reversible_command (Operations::capture);
1559                 _have_captured = true;
1560         }
1561
1562         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
1563
1564         if (abort && did_record) {
1565                 /* no reason to save the session file when we remove sources
1566                  */
1567                 _state_of_the_state = StateOfTheState (_state_of_the_state | InCleanup);
1568         }
1569
1570         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1571                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1572                 if (tr) {
1573                         tr->transport_stopped_wallclock (*now, xnow, abort);
1574                 }
1575         }
1576
1577         if (abort && did_record) {
1578                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1579         }
1580
1581         boost::shared_ptr<RouteList> r = routes.reader ();
1582
1583         if (did_record) {
1584                 commit_reversible_command ();
1585                 /* increase take name */
1586                 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
1587                         string newname = config.get_take_name();
1588                         config.set_take_name(bump_name_number (newname));
1589                 }
1590         }
1591
1592         if (_engine.running()) {
1593                 PostTransportWork ptw = post_transport_work ();
1594
1595                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1596                         (*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
1597                 }
1598                 VCAList v = _vca_manager->vcas ();
1599                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1600                         (*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
1601                 }
1602
1603                 update_latency_compensation ();
1604         }
1605
1606         /* If we are not synced to a "true" external master, and we're not
1607          * handling an explicit locate, we should consider whether or not to
1608          * "auto-return". This could mean going to a specifically requested
1609          * location, or just back to the start of the last roll.
1610          */
1611
1612         if (transport_master_no_external_or_using_engine() && !(ptw & PostTransportLocate)) {
1613
1614                 bool do_locate = false;
1615
1616                 if (_requested_return_sample >= 0) {
1617
1618                         /* explicit return request pre-queued in event list. overrides everything else */
1619
1620                         _transport_sample = _requested_return_sample;
1621
1622                         /* cancel this request */
1623                         _requested_return_sample = -1;
1624                         do_locate = true;
1625
1626                 } else if (Config->get_auto_return_target_list()) {
1627
1628                         samplepos_t jump_to;
1629
1630                         if (select_playhead_priority_target (jump_to)) {
1631
1632                                 /* there's a valid target (we don't care how it
1633                                  * was derived here)
1634                                  */
1635
1636                                 _transport_sample = jump_to;
1637                                 do_locate = true;
1638
1639                         } else if (abort) {
1640
1641                                 /* roll aborted (typically capture) with
1642                                  * auto-return enabled
1643                                  */
1644
1645                                 _transport_sample = _last_roll_location;
1646                                 do_locate = true;
1647
1648                         }
1649                 }
1650
1651
1652                 if (do_locate && synced_to_engine()) {
1653
1654                         /* We will unconditionally locate to _transport_sample
1655                          * below, which will refill playback buffers based on
1656                          * _transport_sample, and maximises the buffering they
1657                          * represent.
1658                          *
1659                          * But if we are synced to engine (JACK), we should
1660                          * locate the engine (JACK) as well. We would follow
1661                          * the engine (JACK) on the next process cycle, but
1662                          * since we're going to do a locate below anyway,
1663                          * it seems pointless to not use just do it ourselves
1664                          * right now, rather than wait for the engine (JACK) to
1665                          * provide the new position on the next cycle.
1666                          *
1667                          * Despite the generic name of the called method
1668                          * (::transport_locate()) this method only does
1669                          * anything if the audio/MIDI backend is JACK.
1670                          */
1671
1672                         _engine.transport_locate (_transport_sample);
1673
1674                 }
1675         }
1676
1677         clear_clicks();
1678         unset_preroll_record_trim ();
1679
1680         /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
1681         */
1682
1683         if (ptw & PostTransportClearSubstate) {
1684                 unset_play_range ();
1685                 if (!Config->get_loop_is_mode()) {
1686                         unset_play_loop ();
1687                 }
1688         }
1689
1690         /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
1691
1692         {
1693                 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
1694                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1695                         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
1696                         (*i)->non_realtime_locate (_transport_sample);
1697
1698                         if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1699                                 finished = false;
1700                                 /* we will be back */
1701                                 return;
1702                         }
1703                 }
1704         }
1705
1706         {
1707                 VCAList v = _vca_manager->vcas ();
1708                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1709                         (*i)->non_realtime_locate (_transport_sample);
1710                 }
1711         }
1712
1713         have_looped = false;
1714
1715         /* don't bother with this stuff if we're disconnected from the engine,
1716            because there will be no process callbacks to deliver stuff from
1717         */
1718
1719         if (_engine.running() && !_engine.freewheeling()) {
1720                 // need to queue this in the next RT cycle
1721                 _send_timecode_update = true;
1722
1723                 if (transport_master()->type() == MTC) {
1724                         send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
1725
1726                         /* This (::non_realtime_stop()) gets called by main
1727                            process thread, which will lead to confusion
1728                            when calling AsyncMIDIPort::write().
1729
1730                            Something must be done. XXX
1731                         */
1732                         send_mmc_locate (_transport_sample);
1733                 }
1734         }
1735
1736         if ((ptw & PostTransportLocate) && get_record_enabled()) {
1737                 /* This is scheduled by realtime_stop(), which is also done
1738                  * when a slave requests /locate/ for an initial sync.
1739                  * We can't hold up the slave for long with a save() here,
1740                  * without breaking its initial sync cycle.
1741                  *
1742                  * save state only if there's no slave or if it's not yet locked.
1743                  */
1744                 if (!transport_master_is_external() || !transport_master()->locked()) {
1745                         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
1746                         SaveSessionRequested (_current_snapshot_name);
1747                         saved = true;
1748                 }
1749         }
1750
1751         /* save the current state of things if appropriate */
1752
1753         if (did_record && !saved) {
1754                 SaveSessionRequested (_current_snapshot_name);
1755         }
1756
1757         if (ptw & PostTransportStop) {
1758                 unset_play_range ();
1759                 if (!Config->get_loop_is_mode()) {
1760                         unset_play_loop ();
1761                 }
1762         }
1763
1764         PositionChanged (_transport_sample); /* EMIT SIGNAL */
1765         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
1766         TransportStateChange (); /* EMIT SIGNAL */
1767         AutomationWatch::instance().transport_stop_automation_watches (_transport_sample);
1768
1769         /* and start it up again if relevant */
1770
1771         if ((ptw & PostTransportLocate) && !config.get_external_sync()) {
1772                 request_transport_speed (1.0);
1773         }
1774 }
1775
1776 void
1777 Session::unset_play_loop ()
1778 {
1779         if (play_loop) {
1780                 play_loop = false;
1781                 clear_events (SessionEvent::AutoLoop);
1782                 set_track_loop (false);
1783
1784
1785                 if (Config->get_seamless_loop()) {
1786                         /* likely need to flush track buffers: this will locate us to wherever we are */
1787                         add_post_transport_work (PostTransportLocate);
1788                         TFSM_EVENT (TransportFSM::ButlerRequired);
1789                 }
1790                 TransportStateChange (); /* EMIT SIGNAL */
1791         }
1792 }
1793
1794 void
1795 Session::set_track_loop (bool yn)
1796 {
1797         Location* loc = _locations->auto_loop_location ();
1798
1799         if (!loc) {
1800                 yn = false;
1801         }
1802
1803         boost::shared_ptr<RouteList> rl = routes.reader ();
1804
1805         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1806                 if (*i && !(*i)->is_private_route()) {
1807                         (*i)->set_loop (yn ? loc : 0);
1808                 }
1809         }
1810 }
1811
1812 samplecnt_t
1813 Session::worst_latency_preroll () const
1814 {
1815         return _worst_output_latency + _worst_input_latency;
1816 }
1817
1818 void
1819 Session::unset_play_range ()
1820 {
1821         _play_range = false;
1822         _clear_event_type (SessionEvent::RangeStop);
1823         _clear_event_type (SessionEvent::RangeLocate);
1824 }
1825
1826 void
1827 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1828 {
1829         SessionEvent* ev;
1830
1831         /* Called from event-processing context */
1832
1833         unset_play_range ();
1834
1835         if (range.empty()) {
1836                 /* _play_range set to false in unset_play_range()
1837                  */
1838                 if (!leave_rolling) {
1839                         /* stop transport */
1840                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1841                         merge_event (ev);
1842                 }
1843                 return;
1844         }
1845
1846         _play_range = true;
1847
1848         /* cancel loop play */
1849         unset_play_loop ();
1850
1851         list<AudioRange>::size_type sz = range.size();
1852
1853         if (sz > 1) {
1854
1855                 list<AudioRange>::iterator i = range.begin();
1856                 list<AudioRange>::iterator next;
1857
1858                 while (i != range.end()) {
1859
1860                         next = i;
1861                         ++next;
1862
1863                         /* locating/stopping is subject to delays for declicking.
1864                          */
1865
1866                         samplepos_t requested_sample = i->end;
1867
1868                         if (requested_sample > current_block_size) {
1869                                 requested_sample -= current_block_size;
1870                         } else {
1871                                 requested_sample = 0;
1872                         }
1873
1874                         if (next == range.end()) {
1875                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_sample, 0, 0.0f);
1876                         } else {
1877                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_sample, (*next).start, 0.0f);
1878                         }
1879
1880                         merge_event (ev);
1881
1882                         i = next;
1883                 }
1884
1885         } else if (sz == 1) {
1886
1887                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1888                 merge_event (ev);
1889
1890         }
1891
1892         /* save range so we can do auto-return etc. */
1893
1894         current_audio_range = range;
1895
1896         /* now start rolling at the right place */
1897
1898         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1899         merge_event (ev);
1900
1901         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1902         TransportStateChange ();
1903 }
1904
1905 void
1906 Session::request_bounded_roll (samplepos_t start, samplepos_t end)
1907 {
1908         AudioRange ar (start, end, 0);
1909         list<AudioRange> lar;
1910
1911         lar.push_back (ar);
1912         request_play_range (&lar, true);
1913 }
1914
1915 void
1916 Session::set_requested_return_sample (samplepos_t return_to)
1917 {
1918         _requested_return_sample = return_to;
1919 }
1920
1921 void
1922 Session::request_roll_at_and_return (samplepos_t start, samplepos_t return_to)
1923 {
1924         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1925         ev->target2_sample = start;
1926         queue_event (ev);
1927 }
1928
1929 void
1930 Session::engine_halted ()
1931 {
1932         /* there will be no more calls to process(), so
1933            we'd better clean up for ourselves, right now.
1934
1935            We can't queue SessionEvents because they only get
1936            handled from within a process callback.
1937         */
1938
1939         /* this just stops the FSM engine ... it doesn't change the state of
1940          * the FSM directly or anything else ... but the FSM will be
1941          * reinitialized when we call its ::start() method from
1942          * ::engine_running() (if we ever get there)
1943          */
1944
1945         _transport_fsm->stop ();
1946
1947         /* Synchronously do the realtime part of a transport stop.
1948          *
1949          * Calling this will cause the butler to asynchronously run
1950          * ::non_realtime_stop() where the rest of the "stop" work will be
1951          * done.
1952          */
1953
1954         realtime_stop (false, true);
1955 }
1956
1957 void
1958 Session::engine_running ()
1959 {
1960         initialize_latencies ();
1961         _transport_fsm->start ();
1962 }
1963
1964 void
1965 Session::xrun_recovery ()
1966 {
1967         ++_xrun_count;
1968
1969         Xrun (_transport_sample); /* EMIT SIGNAL */
1970
1971         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1972
1973                 /* it didn't actually halt, but we need
1974                    to handle things in the same way.
1975                 */
1976
1977                 engine_halted();
1978         }
1979 }
1980
1981 void
1982 Session::route_processors_changed (RouteProcessorChange c)
1983 {
1984         if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
1985                 return;
1986         }
1987
1988         if (c.type == RouteProcessorChange::MeterPointChange) {
1989                 set_dirty ();
1990                 return;
1991         }
1992
1993         if (c.type == RouteProcessorChange::RealTimeChange) {
1994                 set_dirty ();
1995                 return;
1996         }
1997
1998         update_latency_compensation ();
1999         resort_routes ();
2000
2001         set_dirty ();
2002 }
2003
2004 void
2005 Session::allow_auto_play (bool yn)
2006 {
2007         auto_play_legal = yn;
2008 }
2009
2010
2011 void
2012 Session::send_mmc_locate (samplepos_t t)
2013 {
2014         if (t < 0) {
2015                 return;
2016         }
2017
2018         if (!_engine.freewheeling()) {
2019                 Timecode::Time time;
2020                 timecode_time_subframes (t, time);
2021                 send_immediate_mmc (MIDI::MachineControlCommand (time));
2022         }
2023 }
2024
2025 /** Ask the transport to not send timecode until further notice.  The suspension
2026  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
2027  *  should be checked by the caller to find out when.
2028  */
2029 void
2030 Session::request_suspend_timecode_transmission ()
2031 {
2032         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2033         queue_event (ev);
2034 }
2035
2036 void
2037 Session::request_resume_timecode_transmission ()
2038 {
2039         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2040         queue_event (ev);
2041 }
2042
2043 bool
2044 Session::timecode_transmission_suspended () const
2045 {
2046         return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
2047 }
2048
2049 boost::shared_ptr<TransportMaster>
2050 Session::transport_master() const
2051 {
2052         return TransportMasterManager::instance().current();
2053 }
2054
2055 bool
2056 Session::transport_master_is_external () const
2057 {
2058         return TransportMasterManager::instance().current() && config.get_external_sync();
2059 }
2060
2061 bool
2062 Session::transport_master_no_external_or_using_engine () const
2063 {
2064         return !TransportMasterManager::instance().current() || !config.get_external_sync() || (TransportMasterManager::instance().current()->type() == Engine);
2065 }
2066
2067 void
2068 Session::sync_source_changed (SyncSource type, samplepos_t pos, pframes_t cycle_nframes)
2069 {
2070         /* Runs in process() context */
2071
2072         boost::shared_ptr<TransportMaster> master = TransportMasterManager::instance().current();
2073
2074         /* save value of seamless from before the switch */
2075         _was_seamless = Config->get_seamless_loop ();
2076
2077         if (type == Engine) {
2078                 /* JACK cannot support seamless looping at present */
2079                 Config->set_seamless_loop (false);
2080         } else {
2081                 /* reset to whatever the value was before we last switched slaves */
2082                 Config->set_seamless_loop (_was_seamless);
2083         }
2084
2085         if (master->can_loop()) {
2086                 request_play_loop (false);
2087         } else if (master->has_loop()) {
2088                 request_play_loop (true);
2089         }
2090
2091         /* slave change, reset any DiskIO block on disk output because it is no
2092            longer valid with a new slave.
2093         */
2094
2095         DiskReader::dec_no_disk_output ();
2096
2097 #if 0
2098         we should not be treating specific transport masters as special cases because there maybe > 1 of a particular type
2099
2100         boost::shared_ptr<MTC_TransportMaster> mtc_master = boost::dynamic_pointer_cast<MTC_TransportMaster> (master);
2101
2102         if (mtc_master) {
2103                 mtc_master->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
2104                 MTCSyncStateChanged(mtc_master->locked() );
2105         } else {
2106                 if (g_atomic_int_compare_and_exchange (&_mtc_active, 1, 0)) {
2107                         MTCSyncStateChanged( false );
2108                 }
2109                 mtc_status_connection.disconnect ();
2110         }
2111
2112         boost::shared_ptr<LTC_TransportMaster> ltc_master = boost::dynamic_pointer_cast<LTC_TransportMaster> (master);
2113
2114         if (ltc_master) {
2115                 ltc_master->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
2116                 LTCSyncStateChanged (ltc_master->locked() );
2117         } else {
2118                 if (g_atomic_int_compare_and_exchange (&_ltc_active, 1, 0)) {
2119                         LTCSyncStateChanged( false );
2120                 }
2121                 ltc_status_connection.disconnect ();
2122         }
2123 #endif
2124
2125         DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", master));
2126
2127         // need to queue this for next process() cycle
2128         _send_timecode_update = true;
2129
2130         boost::shared_ptr<RouteList> rl = routes.reader();
2131         const bool externally_slaved = transport_master_is_external();
2132
2133         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2134                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2135                 if (tr && !tr->is_private_route()) {
2136                         tr->set_slaved (externally_slaved);
2137                 }
2138         }
2139
2140         set_dirty();
2141 }
2142
2143 bool
2144 Session::transport_stopped() const
2145 {
2146         return _transport_fsm->stopped();
2147 }
2148
2149 bool
2150 Session::transport_rolling() const
2151 {
2152         return _transport_speed != 0.0 && _count_in_samples == 0 && _remaining_latency_preroll == 0;
2153 }
2154
2155 bool
2156 Session::locate_pending () const
2157 {
2158         return _transport_fsm->locating();
2159 }
2160
2161 bool
2162 Session::declick_in_progress () const
2163 {
2164         return _transport_fsm->declick_in_progress();
2165 }