fix #4405, by explicitly cancelling solo when a route's inputs drop to zero
[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         cumulative_rf_motion = 0;
469         reset_rf_scale (0);
470
471         if (did_record) {
472                 begin_reversible_command (Operations::capture);
473                 _have_captured = true;
474         }
475
476         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
477
478         if (abort && did_record) {
479                 /* no reason to save the session file when we remove sources
480                  */
481                 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
482         }
483
484         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
485                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
486                 if (tr) {
487                         tr->transport_stopped_wallclock (*now, xnow, abort);
488                 }
489         }
490
491         if (abort && did_record) {
492                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
493         }
494
495         boost::shared_ptr<RouteList> r = routes.reader ();
496
497         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
498                 if (!(*i)->is_hidden()) {
499                         (*i)->set_pending_declick (0);
500                 }
501         }
502
503         if (did_record) {
504                 commit_reversible_command ();
505         }
506
507         if (_engine.running()) {
508                 PostTransportWork ptw = post_transport_work ();
509                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
510                         (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
511                 }
512                 update_latency_compensation ();
513         }
514
515         bool const auto_return_enabled =
516                 (!config.get_external_sync() && config.get_auto_return());
517
518         if (auto_return_enabled ||
519             (ptw & PostTransportLocate) ||
520             (_requested_return_frame >= 0) ||
521             synced_to_jack()) {
522
523                 if (pending_locate_flush) {
524                         flush_all_inserts ();
525                 }
526
527                 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
528                     !(ptw & PostTransportLocate)) {
529
530                         /* no explicit locate queued */
531
532                         bool do_locate = false;
533
534                         if (_requested_return_frame >= 0) {
535
536                                 /* explicit return request pre-queued in event list. overrides everything else */
537
538                                 cerr << "explicit auto-return to " << _requested_return_frame << endl;
539
540                                 _transport_frame = _requested_return_frame;
541                                 do_locate = true;
542
543                         } else {
544                                 if (config.get_auto_return()) {
545
546                                         if (play_loop) {
547
548                                                 /* don't try to handle loop play when synced to JACK */
549
550                                                 if (!synced_to_jack()) {
551
552                                                         Location *location = _locations->auto_loop_location();
553
554                                                         if (location != 0) {
555                                                                 _transport_frame = location->start();
556                                                         } else {
557                                                                 _transport_frame = _last_roll_location;
558                                                         }
559                                                         do_locate = true;
560                                                 }
561
562                                         } else if (_play_range) {
563
564                                                 /* return to start of range */
565
566                                                 if (!current_audio_range.empty()) {
567                                                         _transport_frame = current_audio_range.front().start;
568                                                         do_locate = true;
569                                                 }
570
571                                         } else {
572
573                                                 /* regular auto-return */
574
575                                                 _transport_frame = _last_roll_location;
576                                                 do_locate = true;
577                                         }
578                                 }
579                         }
580
581                         _requested_return_frame = -1;
582
583                         if (do_locate) {
584                                 _engine.transport_locate (_transport_frame);
585                         }
586                 }
587
588         }
589
590         clear_clicks();
591
592         /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
593         */
594
595         if (ptw & PostTransportClearSubstate) {
596                 _play_range = false;
597                 unset_play_loop ();
598         }
599
600         /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
601
602         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
603         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
604                 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
605                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
606                 if (tr && !tr->hidden()) {
607                         tr->non_realtime_locate (_transport_frame);
608                 }
609
610                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
611                         finished = false;
612                         /* we will be back */
613                         return;
614                 }
615         }
616
617         have_looped = false;
618
619         send_full_time_code (_transport_frame);
620
621         if (!dynamic_cast<MTC_Slave*>(_slave)) {
622                 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
623                 send_mmc_locate (_transport_frame);
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         Timecode::Time time;
1191         timecode_time_subframes (_transport_frame, time);
1192         if (!dynamic_cast<MTC_Slave*>(_slave)) {
1193                 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1194         }
1195
1196         TransportStateChange (); /* EMIT SIGNAL */
1197 }
1198
1199 /** Do any transport work in the audio thread that needs to be done after the
1200  * transport thread is finished.  Audio thread, realtime safe.
1201  */
1202 void
1203 Session::post_transport ()
1204 {
1205         PostTransportWork ptw = post_transport_work ();
1206
1207         if (ptw & PostTransportAudition) {
1208                 if (auditioner && auditioner->auditioning()) {
1209                         process_function = &Session::process_audition;
1210                 } else {
1211                         process_function = &Session::process_with_events;
1212                 }
1213         }
1214
1215         if (ptw & PostTransportStop) {
1216
1217                 transport_sub_state = 0;
1218         }
1219
1220         if (ptw & PostTransportLocate) {
1221
1222                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1223                         start_transport ();
1224
1225                 } else {
1226                         transport_sub_state = 0;
1227                 }
1228         }
1229
1230         set_next_event ();
1231         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1232            know were handled ?
1233         */
1234         set_post_transport_work (PostTransportWork (0));
1235 }
1236
1237 void
1238 Session::reset_rf_scale (framecnt_t motion)
1239 {
1240         cumulative_rf_motion += motion;
1241
1242         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1243                 rf_scale = 1;
1244         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1245                 rf_scale = 4;
1246         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1247                 rf_scale = 10;
1248         } else {
1249                 rf_scale = 100;
1250         }
1251
1252         if (motion != 0) {
1253                 set_dirty();
1254         }
1255 }
1256
1257 void
1258 Session::use_sync_source (Slave* new_slave)
1259 {
1260         /* Runs in process() context */
1261
1262         bool non_rt_required = false;
1263
1264         /* XXX this deletion is problematic because we're in RT context */
1265
1266         delete _slave;
1267         _slave = new_slave;
1268
1269         send_full_time_code (_transport_frame);
1270
1271         boost::shared_ptr<RouteList> rl = routes.reader();
1272         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1273                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1274                 if (tr && !tr->hidden()) {
1275                         if (tr->realtime_set_speed (tr->speed(), true)) {
1276                                 non_rt_required = true;
1277                         }
1278                         tr->set_slaved (_slave != 0);
1279                 }
1280         }
1281
1282         if (non_rt_required) {
1283                 add_post_transport_work (PostTransportSpeed);
1284                 _butler->schedule_transport_work ();
1285         }
1286
1287         set_dirty();
1288 }
1289
1290 void
1291 Session::drop_sync_source ()
1292 {
1293         request_sync_source (0);
1294 }
1295
1296 void
1297 Session::switch_to_sync_source (SyncSource src)
1298 {
1299         Slave* new_slave;
1300
1301         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1302
1303         switch (src) {
1304         case MTC:
1305                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1306                         return;
1307                 }
1308
1309                 try {
1310                         new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
1311                 }
1312
1313                 catch (failed_constructor& err) {
1314                         return;
1315                 }
1316                 break;
1317
1318         case MIDIClock:
1319                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1320                         return;
1321                 }
1322
1323                 try {
1324                         new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
1325                 }
1326
1327                 catch (failed_constructor& err) {
1328                         return;
1329                 }
1330                 break;
1331
1332         case JACK:
1333                 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1334                         return;
1335                 }
1336
1337                 if (config.get_video_pullup() != 0.0f) {
1338                         return;
1339                 }
1340
1341                 new_slave = new JACK_Slave (_engine.jack());
1342                 break;
1343
1344         default:
1345                 new_slave = 0;
1346                 break;
1347         };
1348
1349         request_sync_source (new_slave);
1350 }
1351
1352 void
1353 Session::set_track_speed (Track* track, double speed)
1354 {
1355         if (track->realtime_set_speed (speed, false)) {
1356                 add_post_transport_work (PostTransportSpeed);
1357                 _butler->schedule_transport_work ();
1358                 set_dirty ();
1359         }
1360 }
1361
1362 void
1363 Session::unset_play_range ()
1364 {
1365         _play_range = false;
1366         _clear_event_type (SessionEvent::RangeStop);
1367         _clear_event_type (SessionEvent::RangeLocate);
1368 }
1369
1370 void
1371 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1372 {
1373         SessionEvent* ev;
1374
1375         /* Called from event-processing context */
1376
1377         unset_play_range ();
1378
1379         if (range.empty()) {
1380                 /* _play_range set to false in unset_play_range()
1381                  */
1382                 if (!leave_rolling) {
1383                         /* stop transport */
1384                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1385                         merge_event (ev);
1386                 }
1387                 return;
1388         }
1389
1390         _play_range = true;
1391
1392         /* cancel loop play */
1393         unset_play_loop ();
1394
1395         list<AudioRange>::size_type sz = range.size();
1396
1397         if (sz > 1) {
1398
1399                 list<AudioRange>::iterator i = range.begin();
1400                 list<AudioRange>::iterator next;
1401
1402                 while (i != range.end()) {
1403
1404                         next = i;
1405                         ++next;
1406
1407                         /* locating/stopping is subject to delays for declicking.
1408                          */
1409
1410                         framepos_t requested_frame = i->end;
1411
1412                         if (requested_frame > current_block_size) {
1413                                 requested_frame -= current_block_size;
1414                         } else {
1415                                 requested_frame = 0;
1416                         }
1417
1418                         if (next == range.end()) {
1419                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1420                         } else {
1421                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1422                         }
1423
1424                         merge_event (ev);
1425
1426                         i = next;
1427                 }
1428
1429         } else if (sz == 1) {
1430
1431                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1432                 merge_event (ev);
1433
1434         }
1435
1436         /* save range so we can do auto-return etc. */
1437
1438         current_audio_range = range;
1439
1440         /* now start rolling at the right place */
1441
1442         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1443         merge_event (ev);
1444
1445         TransportStateChange ();
1446 }
1447
1448 void
1449 Session::request_bounded_roll (framepos_t start, framepos_t end)
1450 {
1451         AudioRange ar (start, end, 0);
1452         list<AudioRange> lar;
1453
1454         lar.push_back (ar);
1455         request_play_range (&lar, true);
1456 }
1457 void
1458 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1459 {
1460         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1461         ev->target2_frame = start;
1462         queue_event (ev);
1463 }
1464
1465 void
1466 Session::engine_halted ()
1467 {
1468         bool ignored;
1469
1470         /* there will be no more calls to process(), so
1471            we'd better clean up for ourselves, right now.
1472
1473            but first, make sure the butler is out of
1474            the picture.
1475         */
1476
1477         g_atomic_int_set (&_butler->should_do_transport_work, 0);
1478         set_post_transport_work (PostTransportWork (0));
1479         _butler->stop ();
1480
1481         realtime_stop (false, true);
1482         non_realtime_stop (false, 0, ignored);
1483         transport_sub_state = 0;
1484
1485         TransportStateChange (); /* EMIT SIGNAL */
1486 }
1487
1488
1489 void
1490 Session::xrun_recovery ()
1491 {
1492         Xrun (_transport_frame); /* EMIT SIGNAL */
1493
1494         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1495
1496                 /* it didn't actually halt, but we need
1497                    to handle things in the same way.
1498                 */
1499
1500                 engine_halted();
1501         }
1502 }
1503
1504 void
1505 Session::route_processors_changed (RouteProcessorChange c)
1506 {
1507         if (ignore_route_processor_changes) {
1508                 return;
1509         }
1510
1511         if (c.type == RouteProcessorChange::MeterPointChange) {
1512                 return;
1513         }
1514
1515         update_latency_compensation ();
1516         resort_routes ();
1517
1518         set_dirty ();
1519 }
1520
1521 void
1522 Session::allow_auto_play (bool yn)
1523 {
1524         auto_play_legal = yn;
1525 }
1526
1527 void
1528 Session::reset_jack_connection (jack_client_t* jack)
1529 {
1530         JACK_Slave* js;
1531
1532         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1533                 js->reset_client (jack);
1534         }
1535 }
1536
1537 bool
1538 Session::maybe_stop (framepos_t limit)
1539 {
1540         if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1541                 if (synced_to_jack () && config.get_jack_time_master ()) {
1542                         _engine.transport_stop ();
1543                 } else if (!synced_to_jack ()) {
1544                         stop_transport ();
1545                 }
1546                 return true;
1547         }
1548         return false;
1549 }
1550
1551 void
1552 Session::send_mmc_locate (framepos_t t)
1553 {
1554         Timecode::Time time;
1555         timecode_time_subframes (t, time);
1556         MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
1557 }
1558
1559 /** Ask the transport to not send timecode until further notice.  The suspension
1560  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
1561  *  should be checked by the caller to find out when.
1562  */
1563 void
1564 Session::request_suspend_timecode_transmission ()
1565 {
1566         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1567         queue_event (ev);
1568 }
1569
1570 void
1571 Session::request_resume_timecode_transmission ()
1572 {
1573         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1574         queue_event (ev);
1575 }
1576
1577 bool
1578 Session::timecode_transmission_suspended () const
1579 {
1580         return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
1581 }