more fun and games with latency compensation, and so forth ... not done yet
[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 #include <cmath>
21 #include <cerrno>
22 #include <unistd.h>
23
24 #ifdef WAF_BUILD
25 #include "libardour-config.h"
26 #endif
27
28
29 #include "pbd/undo.h"
30 #include "pbd/error.h"
31 #include "pbd/enumwriter.h"
32 #include "pbd/pthread_utils.h"
33 #include "pbd/memento_command.h"
34
35 #include "midi++/mmc.h"
36 #include "midi++/port.h"
37 #include "midi++/manager.h"
38
39 #include "ardour/ardour.h"
40 #include "ardour/audioengine.h"
41 #include "ardour/auditioner.h"
42 #include "ardour/butler.h"
43 #include "ardour/debug.h"
44 #include "ardour/location.h"
45 #include "ardour/session.h"
46 #include "ardour/slave.h"
47 #include "ardour/operations.h"
48
49 #include "i18n.h"
50
51 using namespace std;
52 using namespace ARDOUR;
53 using namespace PBD;
54
55 void
56 Session::add_post_transport_work (PostTransportWork ptw)
57 {
58         PostTransportWork oldval;
59         PostTransportWork newval;
60         int tries = 0;
61
62         while (tries < 8) {
63                 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
64                 newval = PostTransportWork (oldval | ptw);
65                 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
66                         /* success */
67                         return;
68                 }
69         }
70
71         error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
72 }
73
74 void
75 Session::request_input_change_handling ()
76 {
77         if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
78                 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
79                 queue_event (ev);
80         }
81 }
82
83 void
84 Session::request_sync_source (Slave* new_slave)
85 {
86         SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
87         bool seamless;
88
89         seamless = Config->get_seamless_loop ();
90
91         if (dynamic_cast<JACK_Slave*>(new_slave)) {
92                 /* JACK cannot support seamless looping at present */
93                 Config->set_seamless_loop (false);
94         } else {
95                 /* reset to whatever the value was before we last switched slaves */
96                 Config->set_seamless_loop (_was_seamless);
97         }
98
99         /* save value of seamless from before the switch */
100         _was_seamless = seamless;
101
102         ev->slave = new_slave;
103         queue_event (ev);
104 }
105
106 void
107 Session::request_transport_speed (double speed)
108 {
109         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
110         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
111         queue_event (ev);
112 }
113
114 /** Request a new transport speed, but if the speed parameter is exactly zero then use
115  *  a very small +ve value to prevent the transport actually stopping.  This method should
116  *  be used by callers who are varying transport speed but don't ever want to stop it.
117  */
118 void
119 Session::request_transport_speed_nonzero (double speed)
120 {
121         if (speed == 0) {
122                 speed = DBL_EPSILON;
123         }
124
125         request_transport_speed (speed);
126 }
127
128 void
129 Session::request_track_speed (Track* tr, double speed)
130 {
131         SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
132         ev->set_ptr (tr);
133         queue_event (ev);
134 }
135
136 void
137 Session::request_stop (bool abort, bool clear_state)
138 {
139         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
140         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
141         queue_event (ev);
142 }
143
144 void
145 Session::request_locate (framepos_t target_frame, bool with_roll)
146 {
147         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
148         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
149         queue_event (ev);
150 }
151
152 void
153 Session::force_locate (framepos_t target_frame, bool with_roll)
154 {
155         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
156         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
157         queue_event (ev);
158 }
159
160 void
161 Session::request_play_loop (bool yn, bool leave_rolling)
162 {
163         SessionEvent* ev;
164         Location *location = _locations->auto_loop_location();
165
166         if (location == 0 && yn) {
167                 error << _("Cannot loop - no loop range defined")
168                       << endmsg;
169                 return;
170         }
171
172         ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
173         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
174         queue_event (ev);
175
176         if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
177                 // request an immediate locate to refresh the tracks
178                 // after disabling looping
179                 request_locate (_transport_frame-1, false);
180         }
181 }
182
183 void
184 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
185 {
186         SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
187         if (range) {
188                 ev->audio_range = *range;
189         } else {
190                 ev->audio_range.clear ();
191         }
192         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
193         queue_event (ev);
194 }
195
196 void
197 Session::realtime_stop (bool abort, bool clear_state)
198 {
199         DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
200         PostTransportWork todo = PostTransportWork (0);
201
202         /* assume that when we start, we'll be moving forwards */
203
204         if (_transport_speed < 0.0f) {
205                 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
206         } else {
207                 todo = PostTransportWork (todo | PostTransportStop);
208         }
209
210         /* call routes */
211
212         boost::shared_ptr<RouteList> r = routes.reader ();
213
214         for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
215                 (*i)->realtime_handle_transport_stopped ();
216         }
217
218         if (actively_recording()) {
219
220                 /* move the transport position back to where the
221                    request for a stop was noticed. we rolled
222                    past that point to pick up delayed input (and/or to delick)
223                 */
224
225                 if (worst_playback_latency() > current_block_size) {
226                         /* we rolled past the stop point to pick up data that had
227                            not yet arrived. move back to where the stop occured.
228                         */
229                         decrement_transport_position (current_block_size + (worst_playback_latency() - current_block_size));
230                 } else {
231                         decrement_transport_position (current_block_size);
232                 }
233
234                 /* the duration change is not guaranteed to have happened, but is likely */
235
236                 todo = PostTransportWork (todo | PostTransportDuration);
237         }
238
239         if (abort) {
240                 todo = PostTransportWork (todo | PostTransportAbort);
241         }
242
243         if (clear_state) {
244                 todo = PostTransportWork (todo | PostTransportClearSubstate);
245         }
246
247         if (todo) {
248                 add_post_transport_work (todo);
249         }
250
251         _clear_event_type (SessionEvent::StopOnce);
252         _clear_event_type (SessionEvent::RangeStop);
253         _clear_event_type (SessionEvent::RangeLocate);
254
255         /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
256         disable_record (true, (!Config->get_latched_record_enable() && clear_state));
257         
258         reset_slave_state ();
259
260         _transport_speed = 0;
261         _target_transport_speed = 0;
262
263         g_atomic_int_set (&_playback_load, 100);
264         g_atomic_int_set (&_capture_load, 100);
265
266         if (config.get_use_video_sync()) {
267                 waiting_for_sync_offset = true;
268         }
269
270         transport_sub_state = 0;
271 }
272
273 void
274 Session::butler_transport_work ()
275 {
276   restart:
277         bool finished;
278         PostTransportWork ptw;
279         boost::shared_ptr<RouteList> r = routes.reader ();
280
281         int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
282         finished = true;
283         ptw = post_transport_work();
284
285         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
286
287         if (ptw & PostTransportAdjustPlaybackBuffering) {
288                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
289                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
290                         if (tr) {
291                                 tr->adjust_playback_buffering ();
292                                 /* and refill those buffers ... */
293                                 tr->non_realtime_locate (_transport_frame);
294                         }
295                 }
296                 
297         }
298
299         if (ptw & PostTransportAdjustCaptureBuffering) {
300                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
301                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
302                         if (tr) {
303                                 tr->adjust_capture_buffering ();
304                         }
305                 }
306         }
307
308         if (ptw & PostTransportCurveRealloc) {
309                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
310                         (*i)->curve_reallocate();
311                 }
312         }
313
314         if (ptw & PostTransportInputChange) {
315                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
316                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
317                         if (tr) {
318                                 tr->non_realtime_input_change ();
319                         }
320                 }
321         }
322
323         if (ptw & PostTransportSpeed) {
324                 non_realtime_set_speed ();
325         }
326
327         if (ptw & PostTransportReverse) {
328
329                 clear_clicks();
330                 cumulative_rf_motion = 0;
331                 reset_rf_scale (0);
332
333                 /* don't seek if locate will take care of that in non_realtime_stop() */
334
335                 if (!(ptw & PostTransportLocate)) {
336
337                         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
338                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
339                                 if (tr && !tr->hidden()) {
340                                         tr->non_realtime_locate (_transport_frame);
341                                 }
342                                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
343                                         /* new request, stop seeking, and start again */
344                                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
345                                         goto restart;
346                                 }
347                         }
348                 }
349         }
350
351         if (ptw & PostTransportLocate) {
352                 non_realtime_locate ();
353         }
354
355         if (ptw & PostTransportStop) {
356                 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
357                 if (!finished) {
358                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
359                         goto restart;
360                 }
361         }
362
363         if (ptw & PostTransportOverWrite) {
364                 non_realtime_overwrite (on_entry, finished);
365                 if (!finished) {
366                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
367                         goto restart;
368                 }
369         }
370
371         if (ptw & PostTransportAudition) {
372                 non_realtime_set_audition ();
373         }
374
375         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
376
377         DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
378 }
379
380 void
381 Session::non_realtime_set_speed ()
382 {
383         boost::shared_ptr<RouteList> rl = routes.reader();
384         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
385                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
386                 if (tr) {
387                         tr->non_realtime_set_speed ();
388                 }
389         }
390 }
391
392 void
393 Session::non_realtime_overwrite (int on_entry, bool& finished)
394 {
395         boost::shared_ptr<RouteList> rl = routes.reader();
396         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
397                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
398                 if (tr && tr->pending_overwrite ()) {
399                         tr->overwrite_existing_buffers ();
400                 }
401                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
402                         finished = false;
403                         return;
404                 }
405         }
406 }
407
408
409 void
410 Session::non_realtime_locate ()
411 {
412         boost::shared_ptr<RouteList> rl = routes.reader();
413         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
414                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
415                 if (tr) {
416                         tr->non_realtime_locate (_transport_frame);
417                 }
418         }
419 }
420
421
422 void
423 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
424 {
425         struct tm* now;
426         time_t     xnow;
427         bool       did_record;
428         bool       saved;
429         PostTransportWork ptw = post_transport_work();
430
431         did_record = false;
432         saved = false;
433
434         boost::shared_ptr<RouteList> rl = routes.reader();
435         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
436                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
437                 if (tr && tr->get_captured_frames () != 0) {
438                         did_record = true;
439                         break;
440                 }
441         }
442
443         /* stop and locate are merged here because they share a lot of common stuff */
444
445         time (&xnow);
446         now = localtime (&xnow);
447
448         if (auditioner) {
449                 auditioner->cancel_audition ();
450         }
451
452         clear_clicks();
453         cumulative_rf_motion = 0;
454         reset_rf_scale (0);
455
456         if (did_record) {
457                 begin_reversible_command (Operations::capture);
458                 _have_captured = true;
459         }
460
461         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
462
463         if (abort && did_record) {
464                 /* no reason to save the session file when we remove sources
465                  */
466                 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
467         }
468
469         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
470                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
471                 if (tr) {
472                         tr->transport_stopped_wallclock (*now, xnow, abort);
473                 }
474         }
475
476         if (abort && did_record) {
477                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);                
478         }
479
480         boost::shared_ptr<RouteList> r = routes.reader ();
481
482         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
483                 if (!(*i)->is_hidden()) {
484                         (*i)->set_pending_declick (0);
485                 }
486         }
487
488         if (did_record) {
489                 commit_reversible_command ();
490         }
491
492         if (_engine.running()) {
493                 PostTransportWork ptw = post_transport_work ();
494                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
495                         (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
496                 }
497                 update_latency_compensation ();
498         }
499
500         bool const auto_return_enabled =
501                 (!config.get_external_sync() && config.get_auto_return());
502
503         if (auto_return_enabled ||
504             (ptw & PostTransportLocate) ||
505             (_requested_return_frame >= 0) ||
506             synced_to_jack()) {
507
508                 if (pending_locate_flush) {
509                         flush_all_inserts ();
510                 }
511
512                 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
513                     !(ptw & PostTransportLocate)) {
514
515                         /* no explicit locate queued */
516
517                         bool do_locate = false;
518
519                         if (_requested_return_frame >= 0) {
520
521                                 /* explicit return request pre-queued in event list. overrides everything else */
522                                 
523                                 cerr << "explicit auto-return to " << _requested_return_frame << endl;
524
525                                 _transport_frame = _requested_return_frame;
526                                 do_locate = true;
527
528                         } else {
529                                 if (config.get_auto_return()) {
530
531                                         if (play_loop) {
532
533                                                 /* don't try to handle loop play when synced to JACK */
534
535                                                 if (!synced_to_jack()) {
536
537                                                         Location *location = _locations->auto_loop_location();
538                                                         
539                                                         if (location != 0) {
540                                                                 _transport_frame = location->start();
541                                                         } else {
542                                                                 _transport_frame = _last_roll_location;
543                                                         }
544                                                         do_locate = true;
545                                                 }
546
547                                         } else if (_play_range) {
548
549                                                 /* return to start of range */
550
551                                                 if (!current_audio_range.empty()) {
552                                                         _transport_frame = current_audio_range.front().start;
553                                                         do_locate = true;
554                                                 }
555
556                                         } else {
557                                                 
558                                                 /* regular auto-return */
559                                                 
560                                                 _transport_frame = _last_roll_location;
561                                                 do_locate = true;
562                                         }
563                                 } 
564                         }
565
566                         _requested_return_frame = -1;                   
567
568                         if (do_locate) {
569                                 _engine.transport_locate (_transport_frame);
570                         }
571                 } 
572
573         }
574
575         /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
576         */
577
578         if (ptw & PostTransportClearSubstate) {
579                 _play_range = false;
580                 unset_play_loop ();
581         }
582
583         /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
584
585         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
586         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
587                 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
588                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
589                 if (tr && !tr->hidden()) {
590                         tr->non_realtime_locate (_transport_frame);
591                 }
592
593                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
594                         finished = false;
595                         /* we will be back */
596                         return;
597                 }
598         }
599
600         have_looped = false;
601
602         send_full_time_code (_transport_frame);
603
604         if (!dynamic_cast<MTC_Slave*>(_slave)) {
605                 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
606                 send_mmc_locate (_transport_frame);
607         }
608
609         if ((ptw & PostTransportLocate) && get_record_enabled()) {
610                 /* capture start has been changed, so save pending state */
611                 save_state ("", true);
612                 saved = true;
613         }
614
615         /* always try to get rid of this */
616
617         remove_pending_capture_state ();
618
619         /* save the current state of things if appropriate */
620
621         if (did_record && !saved) {
622                 save_state (_current_snapshot_name);
623         }
624
625         if (ptw & PostTransportStop) {
626                 _play_range = false;
627                 play_loop = false;
628         }
629
630         PositionChanged (_transport_frame); /* EMIT SIGNAL */
631         TransportStateChange (); /* EMIT SIGNAL */
632
633         /* and start it up again if relevant */
634
635         if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
636                 request_transport_speed (1.0);
637                 pending_locate_roll = false;
638         }
639 }
640
641 void
642 Session::check_declick_out ()
643 {
644         bool locate_required = transport_sub_state & PendingLocate;
645
646         /* this is called after a process() iteration. if PendingDeclickOut was set,
647            it means that we were waiting to declick the output (which has just been
648            done) before doing something else. this is where we do that "something else".
649
650            note: called from the audio thread.
651         */
652
653         if (transport_sub_state & PendingDeclickOut) {
654
655                 if (locate_required) {
656                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
657                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
658                 } else {
659                         stop_transport (pending_abort);
660                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
661                 }
662         }
663 }
664
665 void
666 Session::unset_play_loop ()
667 {
668         play_loop = false;
669         clear_events (SessionEvent::AutoLoop);
670         
671         // set all tracks to NOT use internal looping
672         boost::shared_ptr<RouteList> rl = routes.reader ();
673         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
674                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
675                 if (tr && !tr->hidden()) {
676                         tr->set_loop (0);
677                 }
678         }
679 }
680
681 void
682 Session::set_play_loop (bool yn)
683 {
684         /* Called from event-handling context */
685
686         Location *loc;
687
688         if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
689                 /* nothing to do, or can't change loop status while recording */
690                 return;
691         }
692         
693         if (yn && Config->get_seamless_loop() && synced_to_jack()) {
694                 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
695                                              "Recommend changing the configured options"), PROGRAM_NAME)
696                         << endmsg;
697                 return;
698         }
699         
700         if (yn) {
701
702                 play_loop = true;
703
704                 if (loc) {
705
706                         unset_play_range ();
707
708                         if (Config->get_seamless_loop()) {
709                                 // set all tracks to use internal looping
710                                 boost::shared_ptr<RouteList> rl = routes.reader ();
711                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
712                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
713                                         if (tr && !tr->hidden()) {
714                                                 tr->set_loop (loc);
715                                         }
716                                 }
717                         }
718                         else {
719                                 // set all tracks to NOT use internal looping
720                                 boost::shared_ptr<RouteList> rl = routes.reader ();
721                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
722                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
723                                         if (tr && !tr->hidden()) {
724                                                 tr->set_loop (0);
725                                         }
726                                 }
727                         }
728                         
729                         /* put the loop event into the event list */
730                         
731                         SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
732                         merge_event (event);
733
734                         /* locate to start of loop and roll. If doing seamless loop, force a 
735                            locate+buffer refill even if we are positioned there already.
736                         */
737
738                         start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
739                 }
740
741         } else {
742
743                 unset_play_loop ();
744         }
745
746         TransportStateChange ();
747 }
748 void
749 Session::flush_all_inserts ()
750 {
751         boost::shared_ptr<RouteList> r = routes.reader ();
752
753         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
754                 (*i)->flush_processors ();
755         }
756 }
757
758 void
759 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
760 {
761         if (synced_to_jack()) {
762
763                 double sp;
764                 framepos_t pos;
765
766                 _slave->speed_and_position (sp, pos);
767
768                 if (target_frame != pos) {
769
770                         /* tell JACK to change transport position, and we will
771                            follow along later in ::follow_slave()
772                         */
773
774                         _engine.transport_locate (target_frame);
775
776                         if (sp != 1.0f && with_roll) {
777                                 _engine.transport_start ();
778                         }
779
780                 }
781
782         } else {
783                 locate (target_frame, with_roll, with_flush, with_loop, force);
784         }
785 }
786
787 int
788 Session::micro_locate (framecnt_t distance)
789 {
790         boost::shared_ptr<RouteList> rl = routes.reader();
791         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
792                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
793                 if (tr && !tr->can_internal_playback_seek (distance)) {
794                         return -1;
795                 }
796         }
797
798         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
799                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
800                 if (tr) {
801                         tr->internal_playback_seek (distance);
802                 }
803         }
804
805         _transport_frame += distance;
806         return 0;
807 }
808
809 /** @param with_mmc true to send a MMC locate command when the locate is done */
810 void
811 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
812 {
813         if (actively_recording() && !with_loop) {
814                 return;
815         }
816
817         if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
818                 if (with_roll) {
819                         set_transport_speed (1.0, false);
820                 }
821                 loop_changing = false;
822                 Located (); /* EMIT SIGNAL */
823                 return;
824         }
825
826         if (_transport_speed) {
827                 /* schedule a declick. we'll be called again when its done */
828
829                 if (!(transport_sub_state & PendingDeclickOut)) {
830                         transport_sub_state |= (PendingDeclickOut|PendingLocate);
831                         pending_locate_frame = target_frame;
832                         pending_locate_roll = with_roll;
833                         pending_locate_flush = with_flush;
834                         return;
835                 }
836         }
837
838         // Update Timecode time
839         // [DR] FIXME: find out exactly where this should go below
840         _transport_frame = target_frame;
841         timecode_time(_transport_frame, transmitting_timecode_time);
842         outbound_mtc_timecode_frame = _transport_frame;
843         next_quarter_frame_to_send = 0;
844
845         if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
846                 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
847         }
848
849         if (force || !with_loop || loop_changing) {
850
851                 PostTransportWork todo = PostTransportLocate;
852
853                 if (with_roll) {
854                         todo = PostTransportWork (todo | PostTransportRoll);
855                 } 
856
857                 add_post_transport_work (todo);
858                 _butler->schedule_transport_work ();
859
860         } else {
861
862                 /* this is functionally what clear_clicks() does but with a tentative lock */
863
864                 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
865
866                 if (clickm.locked()) {
867
868                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
869                                 delete *i;
870                         }
871
872                         clicks.clear ();
873                 }
874         }
875
876         if (with_roll) {
877                 /* switch from input if we're going to roll */
878                 if (Config->get_monitoring_model() == HardwareMonitoring) {
879                         set_track_monitor_input_status (!config.get_auto_input());
880                 }
881         } else {
882                 /* otherwise we're going to stop, so do the opposite */
883                 if (Config->get_monitoring_model() == HardwareMonitoring) {
884                         set_track_monitor_input_status (true);
885                 }
886         }
887
888         /* cancel looped playback if transport pos outside of loop range */
889         if (play_loop) {
890                 Location* al = _locations->auto_loop_location();
891
892                 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
893                         // cancel looping directly, this is called from event handling context
894                         set_play_loop (false);
895                 }
896                 else if (al && _transport_frame == al->start()) {
897                         if (with_loop) {
898                                 // this is only necessary for seamless looping
899
900                                 boost::shared_ptr<RouteList> rl = routes.reader();
901                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
902                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
903                                         if (tr && tr->record_enabled ()) {
904                                                 // tell it we've looped, so it can deal with the record state
905                                                 tr->transport_looped(_transport_frame);
906                                         }
907                                 }
908                         }
909                         have_looped = true;
910                         TransportLooped(); // EMIT SIGNAL
911                 }
912         }
913
914         loop_changing = false;
915
916         _send_timecode_update = true;
917
918         if (with_mmc) {
919                 send_mmc_locate (_transport_frame);
920         }
921
922         Located (); /* EMIT SIGNAL */
923 }
924
925 /** Set the transport speed.
926  * @param speed New speed
927  * @param abort
928  */
929 void
930 Session::set_transport_speed (double speed, bool abort, bool clear_state)
931 {
932         DEBUG_TRACE (DEBUG::Transport, string_compose ("Set transport speed to %1, abort = %2 clear_state = %3, current = %4\n", speed, abort, clear_state, _transport_speed));
933
934         if (_transport_speed == speed) {
935                 return;
936         }
937
938         _target_transport_speed = fabs(speed);
939
940         /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
941            and user needs. We really need CD-style "skip" playback for ffwd and rewind.
942         */
943
944         if (speed > 0) {
945                 speed = min (8.0, speed);
946         } else if (speed < 0) {
947                 speed = max (-8.0, speed);
948         }
949
950         if (transport_rolling() && speed == 0.0) {
951
952                 /* we are rolling and we want to stop */
953
954                 if (Config->get_monitoring_model() == HardwareMonitoring) {
955                         set_track_monitor_input_status (true);
956                 }
957
958                 if (synced_to_jack ()) {
959                         if (clear_state) {
960                                 /* do this here because our response to the slave won't 
961                                    take care of it.
962                                 */
963                                 _play_range = false;
964                                 unset_play_loop ();
965                         }
966                         _engine.transport_stop ();
967                 } else {
968                         stop_transport (abort);
969                 }
970                 
971                 unset_play_loop ();
972
973         } else if (transport_stopped() && speed == 1.0) {
974
975                 /* we are stopped and we want to start rolling at speed 1 */
976
977                 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
978                         set_track_monitor_input_status (false);
979                 }
980
981                 if (synced_to_jack()) {
982                         _engine.transport_start ();
983                 } else {
984                         start_transport ();
985                 }
986
987         } else {
988
989                 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
990                         warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
991                                                    PROGRAM_NAME)
992                                 << endmsg;
993                         return;
994                 }
995
996                 if (actively_recording()) {
997                         return;
998                 }
999
1000                 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1001                         return;
1002                 }
1003
1004                 if (speed < 0.0 && _transport_frame == 0) {
1005                         return;
1006                 }
1007
1008                 clear_clicks ();
1009
1010                 /* if we are reversing relative to the current speed, or relative to the speed
1011                    before the last stop, then we have to do extra work.
1012                 */
1013                 
1014                 PostTransportWork todo = PostTransportWork (0);
1015
1016                 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1017                         todo = PostTransportWork (todo | PostTransportReverse);
1018                         _last_roll_or_reversal_location = _transport_frame;
1019                 }
1020
1021                 _last_transport_speed = _transport_speed;
1022                 _transport_speed = speed;
1023
1024                 boost::shared_ptr<RouteList> rl = routes.reader();
1025                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1026                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1027                         if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1028                                 todo = PostTransportWork (todo | PostTransportSpeed);
1029                         }
1030                 }
1031
1032                 if (todo) {
1033                         add_post_transport_work (todo);
1034                         _butler->schedule_transport_work ();
1035                 }
1036         }
1037 }
1038
1039
1040 /** Stop the transport.  */
1041 void
1042 Session::stop_transport (bool abort, bool clear_state)
1043 {
1044         if (_transport_speed == 0.0f) {
1045                 return;
1046         }
1047
1048         if (actively_recording() && !(transport_sub_state & StopPendingCapture) && worst_playback_latency() > current_block_size) {
1049
1050                 boost::shared_ptr<RouteList> rl = routes.reader();
1051                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1052                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1053                         if (tr) {
1054                                 tr->prepare_to_stop (_transport_frame);
1055                         }
1056                 }
1057
1058                 /* we need to capture the audio that has still not yet been received by the system
1059                    at the time the stop is requested, so we have to roll past that time.
1060
1061                    we want to declick before stopping, so schedule the autostop for one
1062                    block before the actual end. we'll declick in the subsequent block,
1063                    and then we'll really be stopped.
1064                 */
1065
1066                 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1067                                                      _transport_frame + _worst_input_latency - current_block_size,
1068                                                      0, 0, abort);
1069
1070                 merge_event (ev);
1071                 transport_sub_state |= StopPendingCapture;
1072                 pending_abort = abort;
1073                 return;
1074         }
1075
1076
1077         if ((transport_sub_state & PendingDeclickOut) == 0) {
1078
1079                 if (!(transport_sub_state & StopPendingCapture)) {
1080                         boost::shared_ptr<RouteList> rl = routes.reader();
1081                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1082                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1083                                 if (tr) {
1084                                         tr->prepare_to_stop (_transport_frame);
1085                                 }
1086                         }
1087                 }
1088                 
1089                 transport_sub_state |= PendingDeclickOut;
1090                 /* we'll be called again after the declick */
1091                 pending_abort = abort;
1092                 return;
1093         }
1094
1095         realtime_stop (abort, clear_state);
1096         _butler->schedule_transport_work ();
1097 }
1098
1099 void
1100 Session::start_transport ()
1101 {
1102         _last_roll_location = _transport_frame;
1103         _last_roll_or_reversal_location = _transport_frame;
1104         
1105         have_looped = false;
1106
1107         /* if record status is Enabled, move it to Recording. if its
1108            already Recording, move it to Disabled.
1109         */
1110
1111         switch (record_status()) {
1112         case Enabled:
1113                 if (!config.get_punch_in()) {
1114                         enable_record ();
1115                 }
1116                 break;
1117
1118         case Recording:
1119                 if (!play_loop) {
1120                         disable_record (false);
1121                 }
1122                 break;
1123
1124         default:
1125                 break;
1126         }
1127
1128         transport_sub_state |= PendingDeclickIn;
1129
1130         _transport_speed = 1.0;
1131         _target_transport_speed = 1.0;
1132
1133         boost::shared_ptr<RouteList> rl = routes.reader();
1134         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1135                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1136                 if (tr) {
1137                         tr->realtime_set_speed (tr->speed(), true);
1138                 }
1139                 (*i)->automation_snapshot (_transport_frame, true);
1140         }
1141
1142         Timecode::Time time;
1143         timecode_time_subframes (_transport_frame, time);
1144         if (!dynamic_cast<MTC_Slave*>(_slave)) {
1145                 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1146         }
1147
1148         TransportStateChange (); /* EMIT SIGNAL */
1149 }
1150
1151 /** Do any transport work in the audio thread that needs to be done after the
1152  * transport thread is finished.  Audio thread, realtime safe.
1153  */
1154 void
1155 Session::post_transport ()
1156 {
1157         PostTransportWork ptw = post_transport_work ();
1158
1159         if (ptw & PostTransportAudition) {
1160                 if (auditioner && auditioner->auditioning()) {
1161                         process_function = &Session::process_audition;
1162                 } else {
1163                         process_function = &Session::process_with_events;
1164                 }
1165         }
1166
1167         if (ptw & PostTransportStop) {
1168
1169                 transport_sub_state = 0;
1170         }
1171
1172         if (ptw & PostTransportLocate) {
1173
1174                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1175                         start_transport ();
1176
1177                 } else {
1178                         transport_sub_state = 0;
1179                 }
1180         }
1181
1182         set_next_event ();
1183         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1184            know were handled ?
1185         */
1186         set_post_transport_work (PostTransportWork (0));
1187 }
1188
1189 void
1190 Session::reset_rf_scale (framecnt_t motion)
1191 {
1192         cumulative_rf_motion += motion;
1193
1194         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1195                 rf_scale = 1;
1196         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1197                 rf_scale = 4;
1198         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1199                 rf_scale = 10;
1200         } else {
1201                 rf_scale = 100;
1202         }
1203
1204         if (motion != 0) {
1205                 set_dirty();
1206         }
1207 }
1208
1209 void
1210 Session::use_sync_source (Slave* new_slave)
1211 {
1212         /* Runs in process() context */
1213
1214         bool non_rt_required = false;
1215
1216         /* XXX this deletion is problematic because we're in RT context */
1217
1218         delete _slave;
1219         _slave = new_slave;
1220
1221         boost::shared_ptr<RouteList> rl = routes.reader();
1222         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1223                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1224                 if (tr && !tr->hidden()) {
1225                         if (tr->realtime_set_speed (tr->speed(), true)) {
1226                                 non_rt_required = true;
1227                         }
1228                         tr->set_slaved (_slave != 0);
1229                 }
1230         }
1231
1232         if (non_rt_required) {
1233                 add_post_transport_work (PostTransportSpeed);
1234                 _butler->schedule_transport_work ();
1235         }
1236
1237         set_dirty();
1238 }
1239
1240 void
1241 Session::drop_sync_source ()
1242 {
1243         request_sync_source (0);
1244 }
1245
1246 void
1247 Session::switch_to_sync_source (SyncSource src)
1248 {
1249         Slave* new_slave;
1250
1251         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1252
1253         switch (src) {
1254         case MTC:
1255                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1256                         return;
1257                 }
1258
1259                 try {
1260                         new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
1261                 }
1262
1263                 catch (failed_constructor& err) {
1264                         return;
1265                 }
1266                 break;
1267
1268         case MIDIClock:
1269                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1270                         return;
1271                 }
1272
1273                 try {
1274                         new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
1275                 }
1276                 
1277                 catch (failed_constructor& err) {
1278                         return;
1279                 }
1280                 break;
1281
1282         case JACK:
1283                 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1284                         return;
1285                 }
1286
1287                 if (config.get_video_pullup() != 0.0f) {
1288                         return;
1289                 }
1290
1291                 new_slave = new JACK_Slave (_engine.jack());
1292                 break;
1293                 
1294         default:
1295                 new_slave = 0;
1296                 break;
1297         };
1298
1299         request_sync_source (new_slave);
1300 }
1301
1302 void
1303 Session::reverse_track_buffers ()
1304 {
1305         add_post_transport_work (PostTransportReverse);
1306         _butler->schedule_transport_work ();
1307 }
1308
1309 void
1310 Session::set_track_speed (Track* track, double speed)
1311 {
1312         if (track->realtime_set_speed (speed, false)) {
1313                 add_post_transport_work (PostTransportSpeed);
1314                 _butler->schedule_transport_work ();
1315                 set_dirty ();
1316         }
1317 }
1318
1319 void
1320 Session::unset_play_range ()
1321 {
1322         _play_range = false;
1323         _clear_event_type (SessionEvent::RangeStop);
1324         _clear_event_type (SessionEvent::RangeLocate);
1325 }
1326
1327 void
1328 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1329 {
1330         SessionEvent* ev;
1331
1332         /* Called from event-processing context */
1333
1334         unset_play_range ();
1335         
1336         if (range.empty()) {
1337                 /* _play_range set to false in unset_play_range()
1338                  */
1339                 if (!leave_rolling) {
1340                         /* stop transport */
1341                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1342                         merge_event (ev);
1343                 }
1344                 return;
1345         }
1346
1347         _play_range = true;
1348
1349         /* cancel loop play */
1350         unset_play_loop ();
1351
1352         list<AudioRange>::size_type sz = range.size();
1353         
1354         if (sz > 1) {
1355                 
1356                 list<AudioRange>::iterator i = range.begin(); 
1357                 list<AudioRange>::iterator next;
1358                 
1359                 while (i != range.end()) {
1360                         
1361                         next = i;
1362                         ++next;
1363                         
1364                         /* locating/stopping is subject to delays for declicking.
1365                          */
1366                         
1367                         framepos_t requested_frame = i->end;
1368                         
1369                         if (requested_frame > current_block_size) {
1370                                 requested_frame -= current_block_size;
1371                         } else {
1372                                 requested_frame = 0;
1373                         }
1374                         
1375                         if (next == range.end()) {
1376                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1377                         } else {
1378                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1379                         }
1380                         
1381                         merge_event (ev);
1382                         
1383                         i = next;
1384                 }
1385                 
1386         } else if (sz == 1) {
1387
1388                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1389                 merge_event (ev);
1390                 
1391         } 
1392
1393         /* save range so we can do auto-return etc. */
1394
1395         current_audio_range = range;
1396
1397         /* now start rolling at the right place */
1398
1399         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1400         merge_event (ev);
1401         
1402         TransportStateChange ();
1403 }
1404
1405 void
1406 Session::request_bounded_roll (framepos_t start, framepos_t end)
1407 {
1408         AudioRange ar (start, end, 0);
1409         list<AudioRange> lar;
1410
1411         lar.push_back (ar);
1412         request_play_range (&lar, true);
1413 }
1414 void
1415 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1416 {
1417         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1418         ev->target2_frame = start;
1419         queue_event (ev);
1420 }
1421
1422 void
1423 Session::engine_halted ()
1424 {
1425         bool ignored;
1426
1427         /* there will be no more calls to process(), so
1428            we'd better clean up for ourselves, right now.
1429
1430            but first, make sure the butler is out of
1431            the picture.
1432         */
1433
1434         g_atomic_int_set (&_butler->should_do_transport_work, 0);
1435         set_post_transport_work (PostTransportWork (0));
1436         _butler->stop ();
1437
1438         realtime_stop (false, true);
1439         non_realtime_stop (false, 0, ignored);
1440         transport_sub_state = 0;
1441
1442         TransportStateChange (); /* EMIT SIGNAL */
1443 }
1444
1445
1446 void
1447 Session::xrun_recovery ()
1448 {
1449         Xrun (_transport_frame); //EMIT SIGNAL
1450
1451         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1452
1453                 /* it didn't actually halt, but we need
1454                    to handle things in the same way.
1455                 */
1456
1457                 engine_halted();
1458         }
1459 }
1460
1461 void
1462 Session::route_processors_changed (RouteProcessorChange c)
1463 {
1464         if (c.type == RouteProcessorChange::MeterPointChange) {
1465                 return;
1466         }
1467
1468         update_latency_compensation ();
1469         resort_routes ();
1470 }
1471
1472 void
1473 Session::allow_auto_play (bool yn)
1474 {
1475         auto_play_legal = yn;
1476 }
1477
1478 void
1479 Session::reset_jack_connection (jack_client_t* jack)
1480 {
1481         JACK_Slave* js;
1482
1483         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1484                 js->reset_client (jack);
1485         }
1486 }
1487
1488 bool
1489 Session::maybe_stop (framepos_t limit)
1490 {
1491        if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1492                if (synced_to_jack () && config.get_jack_time_master ()) {
1493                        _engine.transport_stop ();
1494                } else if (!synced_to_jack ()) {
1495                        stop_transport ();
1496                }
1497                return true;
1498        }
1499        return false;
1500 }
1501
1502 void
1503 Session::send_mmc_locate (framepos_t t)
1504 {
1505         Timecode::Time time;
1506         timecode_time_subframes (t, time);
1507         MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
1508 }
1509
1510 /** Ask the transport to not send timecode until further notice.  The suspension
1511  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
1512  *  should be checked by the caller to find out when.
1513  */
1514 void
1515 Session::request_suspend_timecode_transmission ()
1516 {
1517         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1518         queue_event (ev);
1519 }
1520
1521 void
1522 Session::request_resume_timecode_transmission ()
1523 {
1524         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1525         queue_event (ev);
1526 }
1527
1528 bool
1529 Session::timecode_transmission_suspended () const
1530 {
1531         return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
1532 }