4a81e0e798a265238f3c9e81d3dd22dde1dbc7cf
[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_sync_source (Slave* new_slave)
81 {
82         SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
83         bool seamless;
84
85         seamless = Config->get_seamless_loop ();
86
87         if (dynamic_cast<Engine_Slave*>(new_slave)) {
88                 /* JACK cannot support seamless looping at present */
89                 Config->set_seamless_loop (false);
90         } else {
91                 /* reset to whatever the value was before we last switched slaves */
92                 Config->set_seamless_loop (_was_seamless);
93         }
94
95         /* save value of seamless from before the switch */
96         _was_seamless = seamless;
97
98         ev->slave = new_slave;
99         DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
100         queue_event (ev);
101 }
102
103 void
104 Session::request_transport_speed (double speed, bool as_default)
105 {
106         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
107         ev->third_yes_or_no = as_default; // as_default
108         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
109         queue_event (ev);
110 }
111
112 /** Request a new transport speed, but if the speed parameter is exactly zero then use
113  *  a very small +ve value to prevent the transport actually stopping.  This method should
114  *  be used by callers who are varying transport speed but don't ever want to stop it.
115  */
116 void
117 Session::request_transport_speed_nonzero (double speed, bool as_default)
118 {
119         if (speed == 0) {
120                 speed = DBL_EPSILON;
121         }
122
123         request_transport_speed (speed, as_default);
124 }
125
126 void
127 Session::request_stop (bool abort, bool clear_state)
128 {
129         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
130         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));
131         queue_event (ev);
132 }
133
134 void
135 Session::request_locate (framepos_t target_frame, bool with_roll)
136 {
137         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
138         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
139         queue_event (ev);
140 }
141
142 void
143 Session::force_locate (framepos_t target_frame, bool with_roll)
144 {
145         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
146         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
147         queue_event (ev);
148 }
149
150 void
151 Session::unset_preroll_record_punch ()
152 {
153         if (_preroll_record_punch_pos >= 0) {
154                 remove_event (_preroll_record_punch_pos, SessionEvent::RecordStart);
155         }
156         _preroll_record_punch_pos = -1;
157 }
158
159 void
160 Session::unset_preroll_record_trim ()
161 {
162         _preroll_record_trim_len = 0;
163 }
164
165 void
166 Session::request_preroll_record_punch (framepos_t rec_in, framecnt_t preroll)
167 {
168         if (actively_recording ()) {
169                 return;
170         }
171         unset_preroll_record_punch ();
172         unset_preroll_record_trim ();
173         framepos_t start = std::max ((framepos_t)0, rec_in - preroll);
174
175         _preroll_record_punch_pos = rec_in;
176         if (_preroll_record_punch_pos >= 0) {
177                 replace_event (SessionEvent::RecordStart, _preroll_record_punch_pos);
178                 config.set_punch_in (false);
179                 config.set_punch_out (false);
180         }
181         maybe_enable_record ();
182         request_locate (start, true);
183         set_requested_return_frame (rec_in);
184 }
185
186 void
187 Session::request_preroll_record_trim (framepos_t rec_in, framecnt_t preroll)
188 {
189         if (actively_recording ()) {
190                 return;
191         }
192         unset_preroll_record_punch ();
193         unset_preroll_record_trim ();
194
195         config.set_punch_in (false);
196         config.set_punch_out (false);
197
198         framepos_t pos = std::max ((framepos_t)0, rec_in - preroll);
199         _preroll_record_trim_len = preroll;
200         maybe_enable_record ();
201         request_locate (pos, true);
202         set_requested_return_frame (rec_in);
203 }
204
205 void
206 Session::request_count_in_record ()
207 {
208         if (actively_recording ()) {
209                 return;
210         }
211         if (transport_rolling()) {
212                 return;
213         }
214         maybe_enable_record ();
215         _count_in_once = true;
216         request_transport_speed (1.0, true);
217 }
218
219 void
220 Session::request_play_loop (bool yn, bool change_transport_roll)
221 {
222         if (_slave && yn) {
223                 // don't attempt to loop when not using Internal Transport
224                 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
225                 return;
226         }
227
228         SessionEvent* ev;
229         Location *location = _locations->auto_loop_location();
230         double target_speed;
231
232         if (location == 0 && yn) {
233                 error << _("Cannot loop - no loop range defined")
234                       << endmsg;
235                 return;
236         }
237
238         if (change_transport_roll) {
239                 if (transport_rolling()) {
240                         /* start looping at current speed */
241                         target_speed = transport_speed ();
242                 } else {
243                         /* currently stopped */
244                         if (yn) {
245                                 /* start looping at normal speed */
246                                 target_speed = 1.0;
247                         } else {
248                                 target_speed = 0.0;
249                         }
250                 }
251         } else {
252                 /* leave the speed alone */
253                 target_speed = transport_speed ();
254         }
255
256         ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
257         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
258         queue_event (ev);
259
260         if (yn) {
261                 if (!change_transport_roll) {
262                         if (!transport_rolling()) {
263                                 /* we're not changing transport state, but we do want
264                                    to set up position for the new loop. Don't
265                                    do this if we're rolling already.
266                                 */
267                                 request_locate (location->start(), false);
268                         }
269                 }
270         } else {
271                 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
272                         // request an immediate locate to refresh the tracks
273                         // after disabling looping
274                         request_locate (_transport_frame-1, false);
275                 }
276         }
277 }
278
279 void
280 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
281 {
282         SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
283         if (range) {
284                 ev->audio_range = *range;
285         } else {
286                 ev->audio_range.clear ();
287         }
288         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
289         queue_event (ev);
290 }
291
292 void
293 Session::request_cancel_play_range ()
294 {
295         SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
296         queue_event (ev);
297 }
298
299
300 void
301 Session::realtime_stop (bool abort, bool clear_state)
302 {
303         DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
304         PostTransportWork todo = PostTransportWork (0);
305
306         /* assume that when we start, we'll be moving forwards */
307
308         if (_transport_speed < 0.0f) {
309                 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
310                 _default_transport_speed = 1.0;
311         } else {
312                 todo = PostTransportWork (todo | PostTransportStop);
313         }
314
315         /* call routes */
316
317         boost::shared_ptr<RouteList> r = routes.reader ();
318
319         for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
320                 (*i)->realtime_handle_transport_stopped ();
321         }
322
323         DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
324
325         /* the duration change is not guaranteed to have happened, but is likely */
326
327         todo = PostTransportWork (todo | PostTransportDuration);
328
329         if (abort) {
330                 todo = PostTransportWork (todo | PostTransportAbort);
331         }
332
333         if (clear_state) {
334                 todo = PostTransportWork (todo | PostTransportClearSubstate);
335         }
336
337         if (todo) {
338                 add_post_transport_work (todo);
339         }
340
341         _clear_event_type (SessionEvent::StopOnce);
342         _clear_event_type (SessionEvent::RangeStop);
343         _clear_event_type (SessionEvent::RangeLocate);
344
345         /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
346         disable_record (true, (!Config->get_latched_record_enable() && clear_state));
347
348         if (clear_state && !Config->get_loop_is_mode()) {
349                 unset_play_loop ();
350         }
351
352         reset_slave_state ();
353
354         _transport_speed = 0;
355         _target_transport_speed = 0;
356
357         g_atomic_int_set (&_playback_load, 100);
358         g_atomic_int_set (&_capture_load, 100);
359
360         if (config.get_use_video_sync()) {
361                 waiting_for_sync_offset = true;
362         }
363
364         transport_sub_state = 0;
365 }
366
367 void
368 Session::realtime_locate ()
369 {
370         boost::shared_ptr<RouteList> r = routes.reader ();
371         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
372                 (*i)->realtime_locate ();
373         }
374 }
375
376 void
377 Session::butler_transport_work ()
378 {
379         /* Note: this function executes in the butler thread context */
380
381   restart:
382         bool finished;
383         PostTransportWork ptw;
384         boost::shared_ptr<RouteList> r = routes.reader ();
385         uint64_t before;
386
387         int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
388         finished = true;
389         ptw = post_transport_work();
390
391         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
392
393
394         if (ptw & PostTransportLocate) {
395
396                 if (get_play_loop() && !Config->get_seamless_loop()) {
397
398                         DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
399
400                         /* this locate might be happening while we are
401                          * loop recording.
402                          *
403                          * Non-seamless looping will require a locate (below) that
404                          * will reset capture buffers and throw away data.
405                          *
406                          * Rather than first find all tracks and see if they
407                          * have outstanding data, just do a flush anyway. It
408                          * may be cheaper this way anyway, and is certainly
409                          * more accurate.
410                          */
411
412                         bool more_disk_io_to_do = false;
413                         uint32_t errors = 0;
414
415                         do {
416                                 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
417
418                                 if (errors) {
419                                         break;
420                                 }
421
422                                 if (more_disk_io_to_do) {
423                                         continue;
424                                 }
425
426                         } while (false);
427
428                 }
429         }
430
431         if (ptw & PostTransportAdjustPlaybackBuffering) {
432                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
433                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
434                         if (tr) {
435                                 tr->adjust_playback_buffering ();
436                                 /* and refill those buffers ... */
437                         }
438                         (*i)->non_realtime_locate (_transport_frame);
439                 }
440                 VCAList v = _vca_manager->vcas ();
441                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
442                         (*i)->non_realtime_locate (_transport_frame);
443                 }
444         }
445
446         if (ptw & PostTransportAdjustCaptureBuffering) {
447                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
448                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
449                         if (tr) {
450                                 tr->adjust_capture_buffering ();
451                         }
452                 }
453         }
454
455         if (ptw & PostTransportCurveRealloc) {
456                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
457                         (*i)->curve_reallocate();
458                 }
459         }
460
461         if (ptw & PostTransportSpeed) {
462                 non_realtime_set_speed ();
463         }
464
465         if (ptw & PostTransportReverse) {
466
467                 clear_clicks();
468                 cumulative_rf_motion = 0;
469                 reset_rf_scale (0);
470
471                 /* don't seek if locate will take care of that in non_realtime_stop() */
472
473                 if (!(ptw & PostTransportLocate)) {
474                         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
475                                 (*i)->non_realtime_locate (_transport_frame);
476
477                                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
478                                         /* new request, stop seeking, and start again */
479                                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
480                                         goto restart;
481                                 }
482                         }
483                         VCAList v = _vca_manager->vcas ();
484                         for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
485                                 (*i)->non_realtime_locate (_transport_frame);
486                         }
487                 }
488         }
489
490         if (ptw & PostTransportLocate) {
491                 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
492                 non_realtime_locate ();
493         }
494
495         if (ptw & PostTransportStop) {
496                 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
497                 if (!finished) {
498                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
499                         goto restart;
500                 }
501         }
502
503         if (ptw & PostTransportOverWrite) {
504                 non_realtime_overwrite (on_entry, finished);
505                 if (!finished) {
506                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
507                         goto restart;
508                 }
509         }
510
511         if (ptw & PostTransportAudition) {
512                 non_realtime_set_audition ();
513         }
514
515         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
516
517         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()));
518 }
519
520 void
521 Session::non_realtime_set_speed ()
522 {
523         boost::shared_ptr<RouteList> rl = routes.reader();
524         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
525                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
526                 if (tr) {
527                         tr->non_realtime_speed_change ();
528                 }
529         }
530 }
531
532 void
533 Session::non_realtime_overwrite (int on_entry, bool& finished)
534 {
535         boost::shared_ptr<RouteList> rl = routes.reader();
536         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
537                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
538                 if (tr && tr->pending_overwrite ()) {
539                         tr->overwrite_existing_buffers ();
540                 }
541                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
542                         finished = false;
543                         return;
544                 }
545         }
546 }
547
548
549 void
550 Session::non_realtime_locate ()
551 {
552         DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
553
554         if (Config->get_loop_is_mode() && get_play_loop()) {
555
556                 Location *loc  = _locations->auto_loop_location();
557
558                 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
559                         /* jumped out of loop range: stop tracks from looping,
560                            but leave loop (mode) enabled.
561                          */
562                         set_track_loop (false);
563
564                 } else if (loc && Config->get_seamless_loop() &&
565                    ((loc->start() <= _transport_frame) ||
566                    (loc->end() > _transport_frame) ) ) {
567
568                         /* jumping to start of loop. This  might have been done before but it is
569                          * idempotent and cheap. Doing it here ensures that when we start playback
570                          * outside the loop we still flip tracks into the magic seamless mode
571                          * when needed.
572                          */
573                         set_track_loop (true);
574
575                 } else if (loc) {
576                         set_track_loop (false);
577                 }
578
579         } else {
580
581                 /* no more looping .. should have been noticed elsewhere */
582         }
583
584
585         {
586                 boost::shared_ptr<RouteList> rl = routes.reader();
587
588           restart:
589                 const framepos_t tf = _transport_frame;
590
591                 cerr << "\n\n >>> START Non-RT locate on routes to " << tf << "\n\n";
592
593                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
594                         (*i)->non_realtime_locate (_transport_frame);
595                         if (tf != _transport_frame) {
596                                 /* new locate request arrived while processing
597                                    this one. start over.
598                                 */
599                                 cerr << "\n\n\n\n RESTART LOCATE @ " << _transport_frame << endl;
600                                 goto restart;
601                         }
602                 }
603
604                 cerr << "\n\n <<< DONE Non-RT locate on routes\n\n";
605         }
606         {
607                 VCAList v = _vca_manager->vcas ();
608                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
609                         (*i)->non_realtime_locate (_transport_frame);
610                 }
611         }
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->hidden()) {
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         MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1829         if (mtc_slave) {
1830                 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1831                 MTCSyncStateChanged(mtc_slave->locked() );
1832         } else {
1833                 if (g_atomic_int_get (&_mtc_active) ){
1834                         g_atomic_int_set (&_mtc_active, 0);
1835                         MTCSyncStateChanged( false );
1836                 }
1837                 mtc_status_connection.disconnect ();
1838         }
1839
1840         LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1841         if (ltc_slave) {
1842                 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1843                 LTCSyncStateChanged (ltc_slave->locked() );
1844         } else {
1845                 if (g_atomic_int_get (&_ltc_active) ){
1846                         g_atomic_int_set (&_ltc_active, 0);
1847                         LTCSyncStateChanged( false );
1848                 }
1849                 ltc_status_connection.disconnect ();
1850         }
1851
1852         DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1853
1854         // need to queue this for next process() cycle
1855         _send_timecode_update = true;
1856
1857         boost::shared_ptr<RouteList> rl = routes.reader();
1858         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1859                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1860                 if (tr && !tr->hidden()) {
1861                         if (tr->realtime_speed_change()) {
1862                                 non_rt_required = true;
1863                         }
1864                         tr->set_slaved (_slave != 0);
1865                 }
1866         }
1867
1868         if (non_rt_required) {
1869                 add_post_transport_work (PostTransportSpeed);
1870                 _butler->schedule_transport_work ();
1871         }
1872
1873         set_dirty();
1874 }
1875
1876 void
1877 Session::drop_sync_source ()
1878 {
1879         request_sync_source (0);
1880 }
1881
1882 void
1883 Session::switch_to_sync_source (SyncSource src)
1884 {
1885         Slave* new_slave;
1886
1887         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1888
1889         switch (src) {
1890         case MTC:
1891                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1892                         return;
1893                 }
1894
1895                 try {
1896                         new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1897                 }
1898
1899                 catch (failed_constructor& err) {
1900                         return;
1901                 }
1902                 break;
1903
1904         case LTC:
1905                 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1906                         return;
1907                 }
1908
1909                 try {
1910                         new_slave = new LTC_Slave (*this);
1911                 }
1912
1913                 catch (failed_constructor& err) {
1914                         return;
1915                 }
1916
1917                 break;
1918
1919         case MIDIClock:
1920                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1921                         return;
1922                 }
1923
1924                 try {
1925                         new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1926                 }
1927
1928                 catch (failed_constructor& err) {
1929                         return;
1930                 }
1931                 break;
1932
1933         case Engine:
1934                 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1935                         return;
1936                 }
1937
1938                 if (config.get_video_pullup() != 0.0f) {
1939                         return;
1940                 }
1941
1942                 new_slave = new Engine_Slave (*AudioEngine::instance());
1943                 break;
1944
1945         default:
1946                 new_slave = 0;
1947                 break;
1948         };
1949
1950         request_sync_source (new_slave);
1951 }
1952
1953 void
1954 Session::unset_play_range ()
1955 {
1956         _play_range = false;
1957         _clear_event_type (SessionEvent::RangeStop);
1958         _clear_event_type (SessionEvent::RangeLocate);
1959 }
1960
1961 void
1962 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1963 {
1964         SessionEvent* ev;
1965
1966         /* Called from event-processing context */
1967
1968         unset_play_range ();
1969
1970         if (range.empty()) {
1971                 /* _play_range set to false in unset_play_range()
1972                  */
1973                 if (!leave_rolling) {
1974                         /* stop transport */
1975                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1976                         merge_event (ev);
1977                 }
1978                 return;
1979         }
1980
1981         _play_range = true;
1982
1983         /* cancel loop play */
1984         unset_play_loop ();
1985
1986         list<AudioRange>::size_type sz = range.size();
1987
1988         if (sz > 1) {
1989
1990                 list<AudioRange>::iterator i = range.begin();
1991                 list<AudioRange>::iterator next;
1992
1993                 while (i != range.end()) {
1994
1995                         next = i;
1996                         ++next;
1997
1998                         /* locating/stopping is subject to delays for declicking.
1999                          */
2000
2001                         framepos_t requested_frame = i->end;
2002
2003                         if (requested_frame > current_block_size) {
2004                                 requested_frame -= current_block_size;
2005                         } else {
2006                                 requested_frame = 0;
2007                         }
2008
2009                         if (next == range.end()) {
2010                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
2011                         } else {
2012                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2013                         }
2014
2015                         merge_event (ev);
2016
2017                         i = next;
2018                 }
2019
2020         } else if (sz == 1) {
2021
2022                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2023                 merge_event (ev);
2024
2025         }
2026
2027         /* save range so we can do auto-return etc. */
2028
2029         current_audio_range = range;
2030
2031         /* now start rolling at the right place */
2032
2033         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2034         merge_event (ev);
2035
2036         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2037         TransportStateChange ();
2038 }
2039
2040 void
2041 Session::request_bounded_roll (framepos_t start, framepos_t end)
2042 {
2043         AudioRange ar (start, end, 0);
2044         list<AudioRange> lar;
2045
2046         lar.push_back (ar);
2047         request_play_range (&lar, true);
2048 }
2049
2050 void
2051 Session::set_requested_return_frame (framepos_t return_to)
2052 {
2053         _requested_return_frame = return_to;
2054 }
2055
2056 void
2057 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2058 {
2059         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2060         ev->target2_frame = start;
2061         queue_event (ev);
2062 }
2063
2064 void
2065 Session::engine_halted ()
2066 {
2067         bool ignored;
2068
2069         /* there will be no more calls to process(), so
2070            we'd better clean up for ourselves, right now.
2071
2072            but first, make sure the butler is out of
2073            the picture.
2074         */
2075
2076         if (_butler) {
2077                 _butler->stop ();
2078         }
2079
2080         realtime_stop (false, true);
2081         non_realtime_stop (false, 0, ignored);
2082         transport_sub_state = 0;
2083
2084         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2085         TransportStateChange (); /* EMIT SIGNAL */
2086 }
2087
2088
2089 void
2090 Session::xrun_recovery ()
2091 {
2092         ++_xrun_count;
2093
2094         Xrun (_transport_frame); /* EMIT SIGNAL */
2095
2096         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2097
2098                 /* it didn't actually halt, but we need
2099                    to handle things in the same way.
2100                 */
2101
2102                 engine_halted();
2103         }
2104 }
2105
2106 void
2107 Session::route_processors_changed (RouteProcessorChange c)
2108 {
2109         if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2110                 return;
2111         }
2112
2113         if (c.type == RouteProcessorChange::MeterPointChange) {
2114                 set_dirty ();
2115                 return;
2116         }
2117
2118         if (c.type == RouteProcessorChange::RealTimeChange) {
2119                 set_dirty ();
2120                 return;
2121         }
2122
2123         update_latency_compensation ();
2124         resort_routes ();
2125
2126         set_dirty ();
2127 }
2128
2129 void
2130 Session::allow_auto_play (bool yn)
2131 {
2132         auto_play_legal = yn;
2133 }
2134
2135 bool
2136 Session::maybe_stop (framepos_t limit)
2137 {
2138         if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2139                 if (synced_to_engine () && config.get_jack_time_master ()) {
2140                         _engine.transport_stop ();
2141                 } else if (!synced_to_engine ()) {
2142                         stop_transport ();
2143                 }
2144                 return true;
2145         }
2146         return false;
2147 }
2148
2149 void
2150 Session::send_mmc_locate (framepos_t t)
2151 {
2152         if (t < 0) {
2153                 return;
2154         }
2155
2156         if (!_engine.freewheeling()) {
2157                 Timecode::Time time;
2158                 timecode_time_subframes (t, time);
2159                 send_immediate_mmc (MIDI::MachineControlCommand (time));
2160         }
2161 }
2162
2163 /** Ask the transport to not send timecode until further notice.  The suspension
2164  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
2165  *  should be checked by the caller to find out when.
2166  */
2167 void
2168 Session::request_suspend_timecode_transmission ()
2169 {
2170         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2171         queue_event (ev);
2172 }
2173
2174 void
2175 Session::request_resume_timecode_transmission ()
2176 {
2177         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2178         queue_event (ev);
2179 }
2180
2181 bool
2182 Session::timecode_transmission_suspended () const
2183 {
2184         return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
2185 }