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