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