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