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