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