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