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