attempt fix for LTC slave when locating
[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         {
589                 boost::shared_ptr<RouteList> rl = routes.reader();
590
591           restart:
592                 const framepos_t tf = _transport_frame;
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 (_transport_frame);
598                         if (tf != _transport_frame) {
599                                 /* new locate request arrived while processing
600                                    this one. start over.
601                                 */
602                                 cerr << "\n\n\n\n RESTART LOCATE @ " << _transport_frame << endl;
603                                 goto restart;
604                         }
605                 }
606
607                 cerr << "\n\n <<< DONE Non-RT locate on routes\n\n";
608         }
609
610         {
611                 VCAList v = _vca_manager->vcas ();
612                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
613                         (*i)->non_realtime_locate (_transport_frame);
614                 }
615         }
616
617         microseconds_t end = get_microseconds ();
618         cerr << "Locate took " << setprecision (3) << ((end - begin) /1000000.0) << " secs\n";
619
620         _scene_changer->locate (_transport_frame);
621
622         /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
623            rather than clearing them so that the RT thread has to spend time constructing
624            them (in Session::click).
625          */
626         clear_clicks ();
627 }
628
629 #ifdef USE_TRACKS_CODE_FEATURES
630 bool
631 Session::select_playhead_priority_target (framepos_t& jump_to)
632 {
633         jump_to = -1;
634
635         AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
636
637         if (!autoreturn) {
638                 return false;
639         }
640
641         if (Profile->get_trx() && transport_rolling() ) {
642                 // We're playing, so do nothing.
643                 // Next stop will put us where we need to be.
644                 return false;
645         }
646
647         /* Note that the order of checking each AutoReturnTarget flag defines
648            the priority each flag.
649
650            Ardour/Mixbus: Last Locate
651                           Range Selection
652                           Loop Range
653                           Region Selection
654
655            Tracks:        Range Selection
656                           Loop Range
657                           Region Selection
658                           Last Locate
659         */
660
661         if (autoreturn & RangeSelectionStart) {
662                 if (!_range_selection.empty()) {
663                         jump_to = _range_selection.from;
664                 } else {
665                         if (transport_rolling ()) {
666                                 /* Range selection no longer exists, but we're playing,
667                                    so do nothing. Next stop will put us where
668                                    we need to be.
669                                 */
670                                 return false;
671                         }
672                 }
673         }
674
675         if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
676                 /* don't try to handle loop play when synced to JACK */
677
678                 if (!synced_to_engine()) {
679                         Location *location = _locations->auto_loop_location();
680
681                         if (location) {
682                                 jump_to = location->start();
683
684                                 if (Config->get_seamless_loop()) {
685                                         /* need to get track buffers reloaded */
686                                         set_track_loop (true);
687                                 }
688                         }
689                 }
690         }
691
692         if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
693                 if (!_object_selection.empty()) {
694                         jump_to = _object_selection.from;
695                 }
696         }
697
698         if (jump_to < 0 && (autoreturn & LastLocate)) {
699                 jump_to = _last_roll_location;
700         }
701
702         return jump_to >= 0;
703 }
704 #else
705
706 bool
707 Session::select_playhead_priority_target (framepos_t& jump_to)
708 {
709         if (config.get_external_sync() || !config.get_auto_return()) {
710                 return false;
711         }
712
713         jump_to = _last_roll_location;
714         return jump_to >= 0;
715 }
716
717 #endif
718
719 void
720 Session::follow_playhead_priority ()
721 {
722         framepos_t target;
723
724         if (select_playhead_priority_target (target)) {
725                 request_locate (target);
726         }
727 }
728
729 void
730 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
731 {
732         struct tm* now;
733         time_t     xnow;
734         bool       did_record;
735         bool       saved;
736         PostTransportWork ptw = post_transport_work();
737
738         did_record = false;
739         saved = false;
740
741         boost::shared_ptr<RouteList> rl = routes.reader();
742         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
743                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
744                 if (tr && tr->get_captured_frames () != 0) {
745                         did_record = true;
746                         break;
747                 }
748         }
749
750         /* stop and locate are merged here because they share a lot of common stuff */
751
752         time (&xnow);
753         now = localtime (&xnow);
754
755         if (auditioner) {
756                 auditioner->cancel_audition ();
757         }
758
759         cumulative_rf_motion = 0;
760         reset_rf_scale (0);
761
762         if (did_record) {
763                 begin_reversible_command (Operations::capture);
764                 _have_captured = true;
765         }
766
767         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
768
769         if (abort && did_record) {
770                 /* no reason to save the session file when we remove sources
771                  */
772                 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
773         }
774
775         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
776                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
777                 if (tr) {
778                         tr->transport_stopped_wallclock (*now, xnow, abort);
779                 }
780         }
781
782         if (abort && did_record) {
783                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
784         }
785
786         boost::shared_ptr<RouteList> r = routes.reader ();
787
788         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
789                 if (!(*i)->is_auditioner()) {
790                         (*i)->set_pending_declick (0);
791                 }
792         }
793
794         if (did_record) {
795                 commit_reversible_command ();
796                 /* increase take name */
797                 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
798                         string newname = config.get_take_name();
799                         config.set_take_name(bump_name_number (newname));
800                 }
801         }
802
803         if (_engine.running()) {
804                 PostTransportWork ptw = post_transport_work ();
805
806                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
807                         (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
808                 }
809                 VCAList v = _vca_manager->vcas ();
810                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
811                         (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
812                 }
813
814                 update_latency_compensation ();
815         }
816
817         bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
818
819         if (auto_return_enabled ||
820             (ptw & PostTransportLocate) ||
821             (_requested_return_frame >= 0) ||
822             synced_to_engine()) {
823
824                 if (pending_locate_flush) {
825                         flush_all_inserts ();
826                 }
827
828                 // rg: what is the logic behind this case?
829                 // _requested_return_frame should be ignored when synced_to_engine/slaved.
830                 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
831                 // 2016-01-10
832                 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
833                     !(ptw & PostTransportLocate)) {
834
835                         /* no explicit locate queued */
836
837                         bool do_locate = false;
838
839                         if (_requested_return_frame >= 0) {
840
841                                 /* explicit return request pre-queued in event list. overrides everything else */
842
843                                 _transport_frame = _requested_return_frame;
844                                 do_locate = true;
845
846                         } else {
847                                 framepos_t jump_to;
848
849                                 if (select_playhead_priority_target (jump_to)) {
850
851                                         _transport_frame = jump_to;
852                                         do_locate = true;
853
854                                 } else if (abort) {
855
856                                         _transport_frame = _last_roll_location;
857                                         do_locate = true;
858                                 }
859                         }
860
861                         _requested_return_frame = -1;
862
863                         if (do_locate) {
864                                 _engine.transport_locate (_transport_frame);
865                         }
866                 }
867
868         }
869
870         clear_clicks();
871         unset_preroll_record_trim ();
872
873         /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
874         */
875
876         if (ptw & PostTransportClearSubstate) {
877                 unset_play_range ();
878                 if (!Config->get_loop_is_mode()) {
879                         unset_play_loop ();
880                 }
881         }
882
883         /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
884
885         {
886                 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
887                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
888                         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
889                         (*i)->non_realtime_locate (_transport_frame);
890
891                         if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
892                                 finished = false;
893                                 /* we will be back */
894                                 return;
895                         }
896                 }
897         }
898
899         {
900                 VCAList v = _vca_manager->vcas ();
901                 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
902                         (*i)->non_realtime_locate (_transport_frame);
903                 }
904         }
905
906         have_looped = false;
907
908         /* don't bother with this stuff if we're disconnected from the engine,
909            because there will be no process callbacks to deliver stuff from
910         */
911
912         if (_engine.connected() && !_engine.freewheeling()) {
913                 // need to queue this in the next RT cycle
914                 _send_timecode_update = true;
915
916                 if (!dynamic_cast<MTC_Slave*>(_slave)) {
917                         send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
918
919                         /* This (::non_realtime_stop()) gets called by main
920                            process thread, which will lead to confusion
921                            when calling AsyncMIDIPort::write().
922
923                            Something must be done. XXX
924                         */
925                         send_mmc_locate (_transport_frame);
926                 }
927         }
928
929         if ((ptw & PostTransportLocate) && get_record_enabled()) {
930                 /* This is scheduled by realtime_stop(), which is also done
931                  * when a slave requests /locate/ for an initial sync.
932                  * We can't hold up the slave for long with a save() here,
933                  * without breaking its initial sync cycle.
934                  *
935                  * save state only if there's no slave or if it's not yet locked.
936                  */
937                 if (!_slave || !_slave->locked()) {
938                         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
939                         SaveSessionRequested (_current_snapshot_name);
940                         saved = true;
941                 }
942         }
943
944         /* always try to get rid of this */
945
946         remove_pending_capture_state ();
947
948         /* save the current state of things if appropriate */
949
950         if (did_record && !saved) {
951                 SaveSessionRequested (_current_snapshot_name);
952         }
953
954         if (ptw & PostTransportStop) {
955                 unset_play_range ();
956                 if (!Config->get_loop_is_mode()) {
957                         unset_play_loop ();
958                 }
959         }
960
961         PositionChanged (_transport_frame); /* EMIT SIGNAL */
962         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
963         TransportStateChange (); /* EMIT SIGNAL */
964         AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
965
966         /* and start it up again if relevant */
967
968         if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
969                 request_transport_speed (1.0);
970         }
971
972         /* Even if we didn't do a pending locate roll this time, we don't want it hanging
973            around for next time.
974         */
975         pending_locate_roll = false;
976 }
977
978 void
979 Session::check_declick_out ()
980 {
981         bool locate_required = transport_sub_state & PendingLocate;
982
983         /* this is called after a process() iteration. if PendingDeclickOut was set,
984            it means that we were waiting to declick the output (which has just been
985            done) before maybe doing something else. this is where we do that "something else".
986
987            note: called from the audio thread.
988         */
989
990         if (transport_sub_state & PendingDeclickOut) {
991
992                 if (locate_required) {
993                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
994                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
995                 } else {
996                         if (!(transport_sub_state & StopPendingCapture)) {
997                                 stop_transport (pending_abort);
998                                 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
999                         }
1000                 }
1001
1002         } else if (transport_sub_state & PendingLoopDeclickOut) {
1003                 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
1004                 transport_sub_state &= ~PendingLoopDeclickOut;
1005         }
1006 }
1007
1008 void
1009 Session::unset_play_loop ()
1010 {
1011         if (play_loop) {
1012                 play_loop = false;
1013                 clear_events (SessionEvent::AutoLoop);
1014                 clear_events (SessionEvent::AutoLoopDeclick);
1015                 set_track_loop (false);
1016
1017
1018                 if (Config->get_seamless_loop()) {
1019                         /* likely need to flush track buffers: this will locate us to wherever we are */
1020                         add_post_transport_work (PostTransportLocate);
1021                         _butler->schedule_transport_work ();
1022                 }
1023         }
1024 }
1025
1026 void
1027 Session::set_track_loop (bool yn)
1028 {
1029         Location* loc = _locations->auto_loop_location ();
1030
1031         if (!loc) {
1032                 yn = false;
1033         }
1034
1035         boost::shared_ptr<RouteList> rl = routes.reader ();
1036
1037         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1038                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1039                 if (tr && !tr->is_private_route()) {
1040                         tr->set_loop (yn ? loc : 0);
1041                 }
1042         }
1043 }
1044
1045 void
1046 Session::set_play_loop (bool yn, double speed)
1047 {
1048         /* Called from event-handling context */
1049
1050         Location *loc;
1051
1052         if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1053                 /* nothing to do, or can't change loop status while recording */
1054                 return;
1055         }
1056
1057         if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1058                 warning << string_compose (
1059                         _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1060                           "Recommend changing the configured options"), PROGRAM_NAME)
1061                         << endmsg;
1062                 return;
1063         }
1064
1065         if (yn) {
1066
1067                 play_loop = true;
1068                 have_looped = false;
1069
1070                 if (loc) {
1071
1072                         unset_play_range ();
1073
1074                         if (Config->get_seamless_loop()) {
1075                                 if (!Config->get_loop_is_mode()) {
1076                                         /* set all tracks to use internal looping */
1077                                         set_track_loop (true);
1078                                 } else {
1079                                         /* we will do this in the locate to the start OR when we hit the end
1080                                          * of the loop for the first time
1081                                          */
1082                                 }
1083                         } else {
1084                                 /* set all tracks to NOT use internal looping */
1085                                 set_track_loop (false);
1086                         }
1087
1088                         /* Put the delick and loop events in into the event list.  The declick event will
1089                            cause a de-clicking fade-out just before the end of the loop, and it will also result
1090                            in a fade-in when the loop restarts.  The AutoLoop event will peform the actual loop.
1091                         */
1092
1093                         framepos_t dcp;
1094                         framecnt_t dcl;
1095                         auto_loop_declick_range (loc, dcp, dcl);
1096                         merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1097                         merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1098
1099                         /* if requested to roll, locate to start of loop and
1100                          * roll but ONLY if we're not already rolling.
1101
1102                            args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1103                         */
1104
1105                         if (Config->get_loop_is_mode()) {
1106                                 /* loop IS a transport mode: if already
1107                                    rolling, do not locate to loop start.
1108                                 */
1109                                 if (!transport_rolling() && (speed != 0.0)) {
1110                                         start_locate (loc->start(), true, true, false, true);
1111                                 }
1112                         } else {
1113                                 if (speed != 0.0) {
1114                                         start_locate (loc->start(), true, true, false, true);
1115                                 }
1116                         }
1117                 }
1118
1119         } else {
1120
1121                 unset_play_loop ();
1122         }
1123
1124         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1125         TransportStateChange ();
1126 }
1127 void
1128 Session::flush_all_inserts ()
1129 {
1130         boost::shared_ptr<RouteList> r = routes.reader ();
1131
1132         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1133                 (*i)->flush_processors ();
1134         }
1135 }
1136
1137 void
1138 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1139 {
1140         if (target_frame < 0) {
1141                 error << _("Locate called for negative sample position - ignored") << endmsg;
1142                 return;
1143         }
1144
1145         if (synced_to_engine()) {
1146
1147                 double sp;
1148                 framepos_t pos;
1149
1150                 _slave->speed_and_position (sp, pos);
1151
1152                 if (target_frame != pos) {
1153
1154                         if (config.get_jack_time_master()) {
1155                                 /* actually locate now, since otherwise jack_timebase_callback
1156                                    will use the incorrect _transport_frame and report an old
1157                                    and incorrect time to Jack transport
1158                                 */
1159                                 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1160                         }
1161
1162                         /* tell JACK to change transport position, and we will
1163                            follow along later in ::follow_slave()
1164                         */
1165
1166                         _engine.transport_locate (target_frame);
1167
1168                         if (sp != 1.0f && with_roll) {
1169                                 _engine.transport_start ();
1170                         }
1171
1172                 }
1173
1174         } else {
1175                 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1176         }
1177 }
1178
1179 int
1180 Session::micro_locate (framecnt_t distance)
1181 {
1182         boost::shared_ptr<RouteList> rl = routes.reader();
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 && !tr->can_internal_playback_seek (distance)) {
1186                         return -1;
1187                 }
1188         }
1189
1190         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1191                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1192                 if (tr) {
1193                         tr->internal_playback_seek (distance);
1194                 }
1195         }
1196
1197         _transport_frame += distance;
1198         return 0;
1199 }
1200
1201 /** @param with_mmc true to send a MMC locate command when the locate is done */
1202 void
1203 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1204 {
1205         bool need_butler = false;
1206
1207         /* Locates for seamless looping are fairly different from other
1208          * locates. They assume that the diskstream buffers for each track
1209          * already have the correct data in them, and thus there is no need to
1210          * actually tell the tracks to locate. What does need to be done,
1211          * though, is all the housekeeping that is associated with non-linear
1212          * changes in the value of _transport_frame.
1213          */
1214
1215         DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1216                                                        target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1217
1218         if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1219
1220                 /* already at the desired position. Not forced to locate,
1221                    the loop isn't changing, so unless we're told to
1222                    start rolling also, there's nothing to do but
1223                    tell the world where we are (again).
1224                 */
1225
1226                 if (with_roll) {
1227                         set_transport_speed (1.0, 0, false);
1228                 }
1229                 loop_changing = false;
1230                 Located (); /* EMIT SIGNAL */
1231                 return;
1232         }
1233
1234         if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1235                 /* Schedule a declick.  We'll be called again when its done.
1236                    We only do it this way for ordinary locates, not those
1237                    due to **seamless** loops.
1238                 */
1239
1240                 if (!(transport_sub_state & PendingDeclickOut)) {
1241                         transport_sub_state |= (PendingDeclickOut|PendingLocate);
1242                         pending_locate_frame = target_frame;
1243                         pending_locate_roll = with_roll;
1244                         pending_locate_flush = with_flush;
1245                         return;
1246                 }
1247         }
1248
1249         // Update Timecode time
1250         _transport_frame = target_frame;
1251         _last_roll_or_reversal_location = target_frame;
1252         timecode_time(_transport_frame, transmitting_timecode_time);
1253
1254         /* do "stopped" stuff if:
1255          *
1256          * we are rolling AND
1257          *    no autoplay in effect AND
1258          *       we're not going to keep rolling after the locate AND
1259          *           !(playing a loop with JACK sync)
1260          *
1261          */
1262
1263         bool transport_was_stopped = !transport_rolling();
1264
1265         if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1266             (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1267                 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1268                 transport_was_stopped = true;
1269         } else {
1270                 /* otherwise tell the world that we located */
1271                 realtime_locate ();
1272         }
1273
1274         if (force || !for_loop_enabled || loop_changing) {
1275
1276                 PostTransportWork todo = PostTransportLocate;
1277
1278                 if (with_roll && transport_was_stopped) {
1279                         todo = PostTransportWork (todo | PostTransportRoll);
1280                 }
1281
1282                 add_post_transport_work (todo);
1283                 need_butler = true;
1284
1285         } else {
1286
1287                 /* this is functionally what clear_clicks() does but with a tentative lock */
1288
1289                 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1290
1291                 if (clickm.locked()) {
1292
1293                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1294                                 delete *i;
1295                         }
1296
1297                         clicks.clear ();
1298                 }
1299         }
1300
1301         if (with_roll) {
1302                 /* switch from input if we're going to roll */
1303                 if (Config->get_monitoring_model() == HardwareMonitoring) {
1304                         set_track_monitor_input_status (!config.get_auto_input());
1305                 }
1306         } else {
1307                 /* otherwise we're going to stop, so do the opposite */
1308                 if (Config->get_monitoring_model() == HardwareMonitoring) {
1309                         set_track_monitor_input_status (true);
1310                 }
1311         }
1312
1313         /* cancel looped playback if transport pos outside of loop range */
1314         if (play_loop) {
1315
1316                 Location* al = _locations->auto_loop_location();
1317
1318                 if (al) {
1319                         if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1320
1321                                 // located outside the loop: cancel looping directly, this is called from event handling context
1322
1323                                 have_looped = false;
1324
1325                                 if (!Config->get_loop_is_mode()) {
1326                                         set_play_loop (false, _transport_speed);
1327                                 } else {
1328                                         if (Config->get_seamless_loop()) {
1329                                                 /* this will make the non_realtime_locate() in the butler
1330                                                    which then causes seek() in tracks actually do the right
1331                                                    thing.
1332                                                 */
1333                                                 set_track_loop (false);
1334                                         }
1335                                 }
1336
1337                         } else if (_transport_frame == al->start()) {
1338
1339                                 // located to start of loop - this is looping, basically
1340
1341                                 if (!have_looped) {
1342                                         /* first time */
1343                                         if (_last_roll_location != al->start()) {
1344                                                 /* didn't start at loop start - playback must have
1345                                                  * started before loop since we've now hit the loop
1346                                                  * end.
1347                                                  */
1348                                                 add_post_transport_work (PostTransportLocate);
1349                                                 need_butler = true;
1350                                         }
1351
1352                                 }
1353
1354                                 boost::shared_ptr<RouteList> rl = routes.reader();
1355
1356                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1357                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1358
1359                                         if (tr && tr->rec_enable_control()->get_value()) {
1360                                                 // tell it we've looped, so it can deal with the record state
1361                                                 tr->transport_looped (_transport_frame);
1362                                         }
1363                                 }
1364
1365                                 have_looped = true;
1366                                 TransportLooped(); // EMIT SIGNAL
1367                         }
1368                 }
1369         }
1370
1371         if (need_butler) {
1372                 _butler->schedule_transport_work ();
1373         }
1374
1375         loop_changing = false;
1376
1377         _send_timecode_update = true;
1378
1379         if (with_mmc) {
1380                 send_mmc_locate (_transport_frame);
1381         }
1382
1383         _last_roll_location = _last_roll_or_reversal_location =  _transport_frame;
1384         if (!synced_to_engine () || _transport_frame == _engine.transport_frame ()) {
1385                 Located (); /* EMIT SIGNAL */
1386         }
1387 }
1388
1389 /** Set the transport speed.
1390  *  Called from the process thread.
1391  *  @param speed New speed
1392  */
1393 void
1394 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1395 {
1396         DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1397                                                        speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1398
1399         if (_transport_speed == speed) {
1400                 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1401                         _default_transport_speed = 1.0;
1402                 }
1403                 return;
1404         }
1405
1406         if (actively_recording() && speed != 1.0 && speed != 0.0) {
1407                 /* no varispeed during recording */
1408                 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1409                                                        _transport_speed, _transport_frame));
1410                 return;
1411         }
1412
1413         _target_transport_speed = fabs(speed);
1414
1415         /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1416            and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1417         */
1418
1419         if (speed > 0) {
1420                 speed = min (8.0, speed);
1421         } else if (speed < 0) {
1422                 speed = max (-8.0, speed);
1423         }
1424
1425         if (transport_rolling() && speed == 0.0) {
1426
1427                 /* we are rolling and we want to stop */
1428
1429                 if (Config->get_monitoring_model() == HardwareMonitoring) {
1430                         set_track_monitor_input_status (true);
1431                 }
1432
1433                 if (synced_to_engine ()) {
1434                         if (clear_state) {
1435                                 /* do this here because our response to the slave won't
1436                                    take care of it.
1437                                 */
1438                                 _play_range = false;
1439                                 _count_in_once = false;
1440                                 unset_play_loop ();
1441                         }
1442                         _engine.transport_stop ();
1443                 } else {
1444                         bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1445
1446                         if (!auto_return_enabled) {
1447                                 _requested_return_frame = destination_frame;
1448                         }
1449
1450                         stop_transport (abort);
1451                 }
1452
1453         } else if (transport_stopped() && speed == 1.0) {
1454                 if (as_default) {
1455                         _default_transport_speed = speed;
1456                 }
1457                 /* we are stopped and we want to start rolling at speed 1 */
1458
1459                 if (Config->get_loop_is_mode() && play_loop) {
1460
1461                         Location *location = _locations->auto_loop_location();
1462
1463                         if (location != 0) {
1464                                 if (_transport_frame != location->start()) {
1465
1466                                         if (Config->get_seamless_loop()) {
1467                                                 /* force tracks to do their thing */
1468                                                 set_track_loop (true);
1469                                         }
1470
1471                                         /* jump to start and then roll from there */
1472
1473                                         request_locate (location->start(), true);
1474                                         return;
1475                                 }
1476                         }
1477                 }
1478
1479                 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1480                         set_track_monitor_input_status (false);
1481                 }
1482
1483                 if (synced_to_engine()) {
1484                         _engine.transport_start ();
1485                         _count_in_once = false;
1486                 } else {
1487                         start_transport ();
1488                 }
1489
1490         } else {
1491
1492                 /* not zero, not 1.0 ... varispeed */
1493
1494                 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1495                         warning << string_compose (
1496                                 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1497                                 PROGRAM_NAME)
1498                                 << endmsg;
1499                         return;
1500                 }
1501
1502                 if (actively_recording()) {
1503                         return;
1504                 }
1505
1506                 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1507                         return;
1508                 }
1509
1510                 if (speed < 0.0 && _transport_frame == 0) {
1511                         return;
1512                 }
1513
1514                 clear_clicks ();
1515
1516                 /* if we are reversing relative to the current speed, or relative to the speed
1517                    before the last stop, then we have to do extra work.
1518                 */
1519
1520                 PostTransportWork todo = PostTransportWork (0);
1521
1522                 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1523                         todo = PostTransportWork (todo | PostTransportReverse);
1524                         _last_roll_or_reversal_location = _transport_frame;
1525                 }
1526
1527                 _last_transport_speed = _transport_speed;
1528                 _transport_speed = speed;
1529
1530                 if (as_default) {
1531                         _default_transport_speed = speed;
1532                 }
1533
1534                 boost::shared_ptr<RouteList> rl = routes.reader();
1535                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1536                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1537                         if (tr && tr->realtime_speed_change()) {
1538                                 todo = PostTransportWork (todo | PostTransportSpeed);
1539                         }
1540                 }
1541
1542                 if (todo) {
1543                         add_post_transport_work (todo);
1544                         _butler->schedule_transport_work ();
1545                 }
1546
1547                 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1548
1549                 /* throttle signal emissions.
1550                  * when slaved [_last]_transport_speed
1551                  * usually changes every cycle (tiny amounts due to DLL).
1552                  * Emitting a signal every cycle is overkill and unwarranted.
1553                  *
1554                  * Using _last_transport_speed is not acceptable,
1555                  * since it allows for large changes over a long period
1556                  * of time. Hence we introduce a dedicated variable to keep track
1557                  *
1558                  * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1559                  * for TransportStateChange() here is the ShuttleControl display.
1560                  */
1561                 if (fabs (_signalled_varispeed - speed) > .002
1562                     // still, signal hard changes to 1.0 and 0.0:
1563                     || ( speed == 1.0 && _signalled_varispeed != 1.0)
1564                     || ( speed == 0.0 && _signalled_varispeed != 0.0)
1565                    )
1566                 {
1567                         TransportStateChange (); /* EMIT SIGNAL */
1568                         _signalled_varispeed = speed;
1569                 }
1570         }
1571 }
1572
1573
1574 /** Stop the transport.  */
1575 void
1576 Session::stop_transport (bool abort, bool clear_state)
1577 {
1578         _count_in_once = false;
1579         if (_transport_speed == 0.0f) {
1580                 return;
1581         }
1582
1583         DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1584
1585         if (!get_transport_declick_required()) {
1586
1587                 /* stop has not yet been scheduled */
1588
1589                 boost::shared_ptr<RouteList> rl = routes.reader();
1590                 framepos_t stop_target = audible_frame();
1591
1592                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1593                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1594                         if (tr) {
1595                                 tr->prepare_to_stop (_transport_frame, stop_target);
1596                         }
1597                 }
1598
1599                 SubState new_bits;
1600
1601                 if (actively_recording() &&                           /* we are recording */
1602                     worst_input_latency() > current_block_size) {     /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1603
1604                         /* we need to capture the audio that is still somewhere in the pipeline between
1605                            wherever it was generated and the process callback. This means that even though
1606                            the user (or something else)  has asked us to stop, we have to roll
1607                            past this point and then reset the playhead/transport location to
1608                            the position at which the stop was requested.
1609
1610                            we still need playback to "stop" now, however, which is why we schedule
1611                            a declick below.
1612                         */
1613
1614                         DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1615                                                                        _transport_frame, _worst_input_latency,
1616                                                                        _transport_frame + _worst_input_latency,
1617                                                                        abort));
1618
1619                         SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1620                                                              _transport_frame + _worst_input_latency,
1621                                                              0, 0, abort);
1622
1623                         merge_event (ev);
1624
1625                         /* request a declick at the start of the next process cycle() so that playback ceases.
1626                            It will remain silent until we actually stop (at the StopOnce event somewhere in
1627                            the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1628                            does not stop the transport too early.
1629                          */
1630                         new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1631
1632                 } else {
1633
1634                         /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1635
1636                         new_bits = PendingDeclickOut;
1637                         DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1638                 }
1639
1640                 /* we'll be called again after the declick */
1641                 transport_sub_state = SubState (transport_sub_state|new_bits);
1642                 pending_abort = abort;
1643
1644                 return;
1645
1646         } else {
1647
1648                 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1649
1650                 /* declick was scheduled, but we've been called again, which means it is really time to stop
1651
1652                    XXX: we should probably split this off into its own method and call it explicitly.
1653                 */
1654
1655                 realtime_stop (abort, clear_state);
1656                 _butler->schedule_transport_work ();
1657         }
1658 }
1659
1660 /** Called from the process thread */
1661 void
1662 Session::start_transport ()
1663 {
1664         DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1665
1666         _last_roll_location = _transport_frame;
1667         _last_roll_or_reversal_location = _transport_frame;
1668
1669         have_looped = false;
1670
1671         /* if record status is Enabled, move it to Recording. if its
1672            already Recording, move it to Disabled.
1673         */
1674
1675         switch (record_status()) {
1676         case Enabled:
1677                 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1678                         enable_record ();
1679                 }
1680                 break;
1681
1682         case Recording:
1683                 if (!play_loop) {
1684                         disable_record (false);
1685                 }
1686                 break;
1687
1688         default:
1689                 break;
1690         }
1691
1692         transport_sub_state |= PendingDeclickIn;
1693
1694         _transport_speed = _default_transport_speed;
1695         _target_transport_speed = _transport_speed;
1696
1697         boost::shared_ptr<RouteList> rl = routes.reader();
1698         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1699                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1700                 if (tr) {
1701                         tr->realtime_speed_change ();
1702                 }
1703         }
1704
1705         if (!_engine.freewheeling()) {
1706                 Timecode::Time time;
1707                 timecode_time_subframes (_transport_frame, time);
1708                 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1709                         send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1710                 }
1711
1712                 if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
1713                         _count_in_once = false;
1714                         /* calculate count-in duration (in audio samples)
1715                          * - use [fixed] tempo/meter at _transport_frame
1716                          * - calc duration of 1 bar + time-to-beat before or at transport_frame
1717                          */
1718                         const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1719                         const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1720
1721                         const double num = meter.divisions_per_bar ();
1722                         const double den = meter.note_divisor ();
1723                         const double barbeat = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * den / (4. * num);
1724                         const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
1725
1726                         _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1727
1728                         double dt = _count_in_samples / num;
1729                         if (bar_fract == 0) {
1730                                 /* at bar boundary, count-in 2 bars before start. */
1731                                 _count_in_samples *= 2;
1732                         } else {
1733                                 /* beats left after full bar until roll position */
1734                                 _count_in_samples *= 1. + bar_fract;
1735                         }
1736
1737                         int clickbeat = 0;
1738                         framepos_t cf = _transport_frame - _count_in_samples;
1739                         while (cf < _transport_frame) {
1740                                 add_click (cf - _worst_track_latency, clickbeat == 0);
1741                                 cf += dt;
1742                                 clickbeat = fmod (clickbeat + 1, num);
1743                         }
1744                 }
1745         }
1746
1747         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1748         TransportStateChange (); /* EMIT SIGNAL */
1749 }
1750
1751 /** Do any transport work in the audio thread that needs to be done after the
1752  * transport thread is finished.  Audio thread, realtime safe.
1753  */
1754 void
1755 Session::post_transport ()
1756 {
1757         PostTransportWork ptw = post_transport_work ();
1758
1759         if (ptw & PostTransportAudition) {
1760                 if (auditioner && auditioner->auditioning()) {
1761                         process_function = &Session::process_audition;
1762                 } else {
1763                         process_function = &Session::process_with_events;
1764                 }
1765         }
1766
1767         if (ptw & PostTransportStop) {
1768
1769                 transport_sub_state = 0;
1770         }
1771
1772         if (ptw & PostTransportLocate) {
1773
1774                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1775                         _count_in_once = false;
1776                         start_transport ();
1777                 } else {
1778                         transport_sub_state = 0;
1779                 }
1780         }
1781
1782         set_next_event ();
1783         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1784            know were handled ?
1785         */
1786         set_post_transport_work (PostTransportWork (0));
1787 }
1788
1789 void
1790 Session::reset_rf_scale (framecnt_t motion)
1791 {
1792         cumulative_rf_motion += motion;
1793
1794         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1795                 rf_scale = 1;
1796         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1797                 rf_scale = 4;
1798         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1799                 rf_scale = 10;
1800         } else {
1801                 rf_scale = 100;
1802         }
1803
1804         if (motion != 0) {
1805                 set_dirty();
1806         }
1807 }
1808
1809 void
1810 Session::mtc_status_changed (bool yn)
1811 {
1812         g_atomic_int_set (&_mtc_active, yn);
1813         MTCSyncStateChanged( yn );
1814 }
1815
1816 void
1817 Session::ltc_status_changed (bool yn)
1818 {
1819         g_atomic_int_set (&_ltc_active, yn);
1820         LTCSyncStateChanged( yn );
1821 }
1822
1823 void
1824 Session::use_sync_source (Slave* new_slave)
1825 {
1826         /* Runs in process() context */
1827
1828         bool non_rt_required = false;
1829
1830         /* XXX this deletion is problematic because we're in RT context */
1831
1832         delete _slave;
1833         _slave = new_slave;
1834
1835
1836         /* slave change, reset any DiskIO block on disk output because it is no
1837            longer valid with a new slave.
1838         */
1839         DiskReader::set_no_disk_output (false);
1840
1841         MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1842         if (mtc_slave) {
1843                 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1844                 MTCSyncStateChanged(mtc_slave->locked() );
1845         } else {
1846                 if (g_atomic_int_get (&_mtc_active) ){
1847                         g_atomic_int_set (&_mtc_active, 0);
1848                         MTCSyncStateChanged( false );
1849                 }
1850                 mtc_status_connection.disconnect ();
1851         }
1852
1853         LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1854         if (ltc_slave) {
1855                 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1856                 LTCSyncStateChanged (ltc_slave->locked() );
1857         } else {
1858                 if (g_atomic_int_get (&_ltc_active) ){
1859                         g_atomic_int_set (&_ltc_active, 0);
1860                         LTCSyncStateChanged( false );
1861                 }
1862                 ltc_status_connection.disconnect ();
1863         }
1864
1865         DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1866
1867         // need to queue this for next process() cycle
1868         _send_timecode_update = true;
1869
1870         boost::shared_ptr<RouteList> rl = routes.reader();
1871         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1872                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1873                 if (tr && !tr->is_private_route()) {
1874                         if (tr->realtime_speed_change()) {
1875                                 non_rt_required = true;
1876                         }
1877                         tr->set_slaved (_slave != 0);
1878                 }
1879         }
1880
1881         if (non_rt_required) {
1882                 add_post_transport_work (PostTransportSpeed);
1883                 _butler->schedule_transport_work ();
1884         }
1885
1886         set_dirty();
1887 }
1888
1889 void
1890 Session::drop_sync_source ()
1891 {
1892         request_sync_source (0);
1893 }
1894
1895 void
1896 Session::switch_to_sync_source (SyncSource src)
1897 {
1898         Slave* new_slave;
1899
1900         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1901
1902         switch (src) {
1903         case MTC:
1904                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1905                         return;
1906                 }
1907
1908                 try {
1909                         new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1910                 }
1911
1912                 catch (failed_constructor& err) {
1913                         return;
1914                 }
1915                 break;
1916
1917         case LTC:
1918                 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1919                         return;
1920                 }
1921
1922                 try {
1923                         new_slave = new LTC_Slave (*this);
1924                 }
1925
1926                 catch (failed_constructor& err) {
1927                         return;
1928                 }
1929
1930                 break;
1931
1932         case MIDIClock:
1933                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1934                         return;
1935                 }
1936
1937                 try {
1938                         new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1939                 }
1940
1941                 catch (failed_constructor& err) {
1942                         return;
1943                 }
1944                 break;
1945
1946         case Engine:
1947                 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1948                         return;
1949                 }
1950
1951                 if (config.get_video_pullup() != 0.0f) {
1952                         return;
1953                 }
1954
1955                 new_slave = new Engine_Slave (*AudioEngine::instance());
1956                 break;
1957
1958         default:
1959                 new_slave = 0;
1960                 break;
1961         };
1962
1963         request_sync_source (new_slave);
1964 }
1965
1966 void
1967 Session::unset_play_range ()
1968 {
1969         _play_range = false;
1970         _clear_event_type (SessionEvent::RangeStop);
1971         _clear_event_type (SessionEvent::RangeLocate);
1972 }
1973
1974 void
1975 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1976 {
1977         SessionEvent* ev;
1978
1979         /* Called from event-processing context */
1980
1981         unset_play_range ();
1982
1983         if (range.empty()) {
1984                 /* _play_range set to false in unset_play_range()
1985                  */
1986                 if (!leave_rolling) {
1987                         /* stop transport */
1988                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1989                         merge_event (ev);
1990                 }
1991                 return;
1992         }
1993
1994         _play_range = true;
1995
1996         /* cancel loop play */
1997         unset_play_loop ();
1998
1999         list<AudioRange>::size_type sz = range.size();
2000
2001         if (sz > 1) {
2002
2003                 list<AudioRange>::iterator i = range.begin();
2004                 list<AudioRange>::iterator next;
2005
2006                 while (i != range.end()) {
2007
2008                         next = i;
2009                         ++next;
2010
2011                         /* locating/stopping is subject to delays for declicking.
2012                          */
2013
2014                         framepos_t requested_frame = i->end;
2015
2016                         if (requested_frame > current_block_size) {
2017                                 requested_frame -= current_block_size;
2018                         } else {
2019                                 requested_frame = 0;
2020                         }
2021
2022                         if (next == range.end()) {
2023                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
2024                         } else {
2025                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2026                         }
2027
2028                         merge_event (ev);
2029
2030                         i = next;
2031                 }
2032
2033         } else if (sz == 1) {
2034
2035                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2036                 merge_event (ev);
2037
2038         }
2039
2040         /* save range so we can do auto-return etc. */
2041
2042         current_audio_range = range;
2043
2044         /* now start rolling at the right place */
2045
2046         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2047         merge_event (ev);
2048
2049         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2050         TransportStateChange ();
2051 }
2052
2053 void
2054 Session::request_bounded_roll (framepos_t start, framepos_t end)
2055 {
2056         AudioRange ar (start, end, 0);
2057         list<AudioRange> lar;
2058
2059         lar.push_back (ar);
2060         request_play_range (&lar, true);
2061 }
2062
2063 void
2064 Session::set_requested_return_frame (framepos_t return_to)
2065 {
2066         _requested_return_frame = return_to;
2067 }
2068
2069 void
2070 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2071 {
2072         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2073         ev->target2_frame = start;
2074         queue_event (ev);
2075 }
2076
2077 void
2078 Session::engine_halted ()
2079 {
2080         bool ignored;
2081
2082         /* there will be no more calls to process(), so
2083            we'd better clean up for ourselves, right now.
2084
2085            but first, make sure the butler is out of
2086            the picture.
2087         */
2088
2089         if (_butler) {
2090                 _butler->stop ();
2091         }
2092
2093         realtime_stop (false, true);
2094         non_realtime_stop (false, 0, ignored);
2095         transport_sub_state = 0;
2096
2097         DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2098         TransportStateChange (); /* EMIT SIGNAL */
2099 }
2100
2101
2102 void
2103 Session::xrun_recovery ()
2104 {
2105         ++_xrun_count;
2106
2107         Xrun (_transport_frame); /* EMIT SIGNAL */
2108
2109         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2110
2111                 /* it didn't actually halt, but we need
2112                    to handle things in the same way.
2113                 */
2114
2115                 engine_halted();
2116         }
2117 }
2118
2119 void
2120 Session::route_processors_changed (RouteProcessorChange c)
2121 {
2122         if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2123                 return;
2124         }
2125
2126         if (c.type == RouteProcessorChange::MeterPointChange) {
2127                 set_dirty ();
2128                 return;
2129         }
2130
2131         if (c.type == RouteProcessorChange::RealTimeChange) {
2132                 set_dirty ();
2133                 return;
2134         }
2135
2136         update_latency_compensation ();
2137         resort_routes ();
2138
2139         set_dirty ();
2140 }
2141
2142 void
2143 Session::allow_auto_play (bool yn)
2144 {
2145         auto_play_legal = yn;
2146 }
2147
2148 bool
2149 Session::maybe_stop (framepos_t limit)
2150 {
2151         if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2152                 if (synced_to_engine () && config.get_jack_time_master ()) {
2153                         _engine.transport_stop ();
2154                 } else if (!synced_to_engine ()) {
2155                         stop_transport ();
2156                 }
2157                 return true;
2158         }
2159         return false;
2160 }
2161
2162 void
2163 Session::send_mmc_locate (framepos_t t)
2164 {
2165         if (t < 0) {
2166                 return;
2167         }
2168
2169         if (!_engine.freewheeling()) {
2170                 Timecode::Time time;
2171                 timecode_time_subframes (t, time);
2172                 send_immediate_mmc (MIDI::MachineControlCommand (time));
2173         }
2174 }
2175
2176 /** Ask the transport to not send timecode until further notice.  The suspension
2177  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
2178  *  should be checked by the caller to find out when.
2179  */
2180 void
2181 Session::request_suspend_timecode_transmission ()
2182 {
2183         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2184         queue_event (ev);
2185 }
2186
2187 void
2188 Session::request_resume_timecode_transmission ()
2189 {
2190         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2191         queue_event (ev);
2192 }
2193
2194 bool
2195 Session::timecode_transmission_suspended () const
2196 {
2197         return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
2198 }