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