Fix some oddities with playhead movement when locating
[ardour.git] / libs / ardour / session_transport.cc
1 /*
2     Copyright (C) 1999-2003 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include <cmath>
25 #include <cerrno>
26 #include <unistd.h>
27
28 #include "pbd/undo.h"
29 #include "pbd/error.h"
30 #include "pbd/enumwriter.h"
31 #include "pbd/pthread_utils.h"
32 #include "pbd/memento_command.h"
33
34 #include "midi++/mmc.h"
35 #include "midi++/port.h"
36 #include "midi++/manager.h"
37
38 #include "ardour/audioengine.h"
39 #include "ardour/auditioner.h"
40 #include "ardour/butler.h"
41 #include "ardour/click.h"
42 #include "ardour/debug.h"
43 #include "ardour/location.h"
44 #include "ardour/session.h"
45 #include "ardour/slave.h"
46 #include "ardour/operations.h"
47
48 #include "i18n.h"
49
50 using namespace std;
51 using namespace ARDOUR;
52 using namespace PBD;
53
54 void
55 Session::add_post_transport_work (PostTransportWork ptw)
56 {
57         PostTransportWork oldval;
58         PostTransportWork newval;
59         int tries = 0;
60
61         while (tries < 8) {
62                 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
63                 newval = PostTransportWork (oldval | ptw);
64                 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
65                         /* success */
66                         return;
67                 }
68         }
69
70         error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
71 }
72
73 void
74 Session::request_input_change_handling ()
75 {
76         if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
77                 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
78                 queue_event (ev);
79         }
80 }
81
82 void
83 Session::request_sync_source (Slave* new_slave)
84 {
85         SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
86         bool seamless;
87
88         seamless = Config->get_seamless_loop ();
89
90         if (dynamic_cast<JACK_Slave*>(new_slave)) {
91                 /* JACK cannot support seamless looping at present */
92                 Config->set_seamless_loop (false);
93         } else {
94                 /* reset to whatever the value was before we last switched slaves */
95                 Config->set_seamless_loop (_was_seamless);
96         }
97
98         /* save value of seamless from before the switch */
99         _was_seamless = seamless;
100
101         ev->slave = new_slave;
102         queue_event (ev);
103 }
104
105 void
106 Session::request_transport_speed (double speed, bool as_default)
107 {
108         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
109         ev->third_yes_or_no = true;
110         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
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, bool as_default)
120 {
121         if (speed == 0) {
122                 speed = DBL_EPSILON;
123         }
124
125         request_transport_speed (speed, as_default);
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         cumulative_rf_motion = 0;
468         reset_rf_scale (0);
469
470         if (did_record) {
471                 begin_reversible_command (Operations::capture);
472                 _have_captured = true;
473         }
474
475         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
476
477         if (abort && did_record) {
478                 /* no reason to save the session file when we remove sources
479                  */
480                 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
481         }
482
483         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
484                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
485                 if (tr) {
486                         tr->transport_stopped_wallclock (*now, xnow, abort);
487                 }
488         }
489
490         if (abort && did_record) {
491                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
492         }
493
494         boost::shared_ptr<RouteList> r = routes.reader ();
495
496         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
497                 if (!(*i)->is_hidden()) {
498                         (*i)->set_pending_declick (0);
499                 }
500         }
501
502         if (did_record) {
503                 commit_reversible_command ();
504         }
505
506         if (_engine.running()) {
507                 PostTransportWork ptw = post_transport_work ();
508                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
509                         (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
510                 }
511                 update_latency_compensation ();
512         }
513
514         bool const auto_return_enabled =
515                 (!config.get_external_sync() && config.get_auto_return());
516
517         if (auto_return_enabled ||
518             (ptw & PostTransportLocate) ||
519             (_requested_return_frame >= 0) ||
520             synced_to_jack()) {
521
522                 if (pending_locate_flush) {
523                         flush_all_inserts ();
524                 }
525
526                 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
527                     !(ptw & PostTransportLocate)) {
528
529                         /* no explicit locate queued */
530
531                         bool do_locate = false;
532
533                         if (_requested_return_frame >= 0) {
534
535                                 /* explicit return request pre-queued in event list. overrides everything else */
536
537                                 cerr << "explicit auto-return to " << _requested_return_frame << endl;
538
539                                 _transport_frame = _requested_return_frame;
540                                 do_locate = true;
541
542                         } else {
543                                 if (config.get_auto_return()) {
544
545                                         if (play_loop) {
546
547                                                 /* don't try to handle loop play when synced to JACK */
548
549                                                 if (!synced_to_jack()) {
550
551                                                         Location *location = _locations->auto_loop_location();
552
553                                                         if (location != 0) {
554                                                                 _transport_frame = location->start();
555                                                         } else {
556                                                                 _transport_frame = _last_roll_location;
557                                                         }
558                                                         do_locate = true;
559                                                 }
560
561                                         } else if (_play_range) {
562
563                                                 /* return to start of range */
564
565                                                 if (!current_audio_range.empty()) {
566                                                         _transport_frame = current_audio_range.front().start;
567                                                         do_locate = true;
568                                                 }
569
570                                         } else {
571
572                                                 /* regular auto-return */
573
574                                                 _transport_frame = _last_roll_location;
575                                                 do_locate = true;
576                                         }
577                                 }
578                         }
579
580                         _requested_return_frame = -1;
581
582                         if (do_locate) {
583                                 _engine.transport_locate (_transport_frame);
584                         }
585                 }
586
587         }
588
589         clear_clicks();
590
591         /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
592         */
593
594         if (ptw & PostTransportClearSubstate) {
595                 _play_range = false;
596                 unset_play_loop ();
597         }
598
599         /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
600
601         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
602         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
603                 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
604                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
605                 if (tr && !tr->hidden()) {
606                         tr->non_realtime_locate (_transport_frame);
607                 }
608
609                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
610                         finished = false;
611                         /* we will be back */
612                         return;
613                 }
614         }
615
616         have_looped = false;
617
618         if (!_engine.freewheeling()) {
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
627         if ((ptw & PostTransportLocate) && get_record_enabled()) {
628                 /* capture start has been changed, so save pending state */
629                 save_state ("", true);
630                 saved = true;
631         }
632
633         /* always try to get rid of this */
634
635         remove_pending_capture_state ();
636
637         /* save the current state of things if appropriate */
638
639         if (did_record && !saved) {
640                 save_state (_current_snapshot_name);
641         }
642
643         if (ptw & PostTransportStop) {
644                 _play_range = false;
645                 play_loop = false;
646         }
647
648         PositionChanged (_transport_frame); /* EMIT SIGNAL */
649         TransportStateChange (); /* EMIT SIGNAL */
650
651         /* and start it up again if relevant */
652
653         if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
654                 request_transport_speed (1.0);
655                 pending_locate_roll = false;
656         }
657 }
658
659 void
660 Session::check_declick_out ()
661 {
662         bool locate_required = transport_sub_state & PendingLocate;
663
664         /* this is called after a process() iteration. if PendingDeclickOut was set,
665            it means that we were waiting to declick the output (which has just been
666            done) before maybe doing something else. this is where we do that "something else".
667
668            note: called from the audio thread.
669         */
670
671         if (transport_sub_state & PendingDeclickOut) {
672
673                 if (locate_required) {
674                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
675                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
676                 } else {
677                         stop_transport (pending_abort);
678                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
679                 }
680
681         } else if (transport_sub_state & PendingLoopDeclickOut) {
682                 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
683                 transport_sub_state &= ~PendingLoopDeclickOut;
684         }
685 }
686
687 void
688 Session::unset_play_loop ()
689 {
690         play_loop = false;
691         clear_events (SessionEvent::AutoLoop);
692         clear_events (SessionEvent::AutoLoopDeclick);
693
694         // set all tracks to NOT use internal looping
695         boost::shared_ptr<RouteList> rl = routes.reader ();
696         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
697                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
698                 if (tr && !tr->hidden()) {
699                         tr->set_loop (0);
700                 }
701         }
702 }
703
704 void
705 Session::set_play_loop (bool yn)
706 {
707         /* Called from event-handling context */
708
709         Location *loc;
710
711         if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
712                 /* nothing to do, or can't change loop status while recording */
713                 return;
714         }
715
716         if (yn && Config->get_seamless_loop() && synced_to_jack()) {
717                 warning << string_compose (
718                         _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
719                           "Recommend changing the configured options"), PROGRAM_NAME)
720                         << endmsg;
721                 return;
722         }
723
724         if (yn) {
725
726                 play_loop = true;
727
728                 if (loc) {
729
730                         unset_play_range ();
731
732                         if (Config->get_seamless_loop()) {
733                                 // set all tracks to use internal looping
734                                 boost::shared_ptr<RouteList> rl = routes.reader ();
735                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
736                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
737                                         if (tr && !tr->hidden()) {
738                                                 tr->set_loop (loc);
739                                         }
740                                 }
741                         }
742                         else {
743                                 // set all tracks to NOT use internal looping
744                                 boost::shared_ptr<RouteList> rl = routes.reader ();
745                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
746                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
747                                         if (tr && !tr->hidden()) {
748                                                 tr->set_loop (0);
749                                         }
750                                 }
751                         }
752
753                         /* Put the delick and loop events in into the event list.  The declick event will
754                            cause a de-clicking fade-out just before the end of the loop, and it will also result
755                            in a fade-in when the loop restarts.  The AutoLoop event will peform the actual loop.
756                         */
757
758                         framepos_t dcp;
759                         framecnt_t dcl;
760                         auto_loop_declick_range (loc, dcp, dcl);
761                         merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
762                         merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
763
764                         /* locate to start of loop and roll. 
765
766                            args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
767                         */
768
769                         start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
770                 }
771
772         } else {
773
774                 unset_play_loop ();
775         }
776
777         TransportStateChange ();
778 }
779 void
780 Session::flush_all_inserts ()
781 {
782         boost::shared_ptr<RouteList> r = routes.reader ();
783
784         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
785                 (*i)->flush_processors ();
786         }
787 }
788
789 void
790 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
791 {
792         if (synced_to_jack()) {
793
794                 double sp;
795                 framepos_t pos;
796
797                 _slave->speed_and_position (sp, pos);
798
799                 if (target_frame != pos) {
800
801                         /* tell JACK to change transport position, and we will
802                            follow along later in ::follow_slave()
803                         */
804
805                         _engine.transport_locate (target_frame);
806
807                         if (sp != 1.0f && with_roll) {
808                                 _engine.transport_start ();
809                         }
810
811                 }
812
813         } else {
814                 locate (target_frame, with_roll, with_flush, with_loop, force);
815         }
816 }
817
818 int
819 Session::micro_locate (framecnt_t distance)
820 {
821         boost::shared_ptr<RouteList> rl = routes.reader();
822         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
823                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
824                 if (tr && !tr->can_internal_playback_seek (distance)) {
825                         return -1;
826                 }
827         }
828
829         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
830                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
831                 if (tr) {
832                         tr->internal_playback_seek (distance);
833                 }
834         }
835
836         _transport_frame += distance;
837         return 0;
838 }
839
840 /** @param with_mmc true to send a MMC locate command when the locate is done */
841 void
842 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_seamless_loop, bool force, bool with_mmc)
843 {
844         /* Locates for seamless looping are fairly different from other
845          * locates. They assume that the diskstream buffers for each track
846          * already have the correct data in them, and thus there is no need to
847          * actually tell the tracks to locate. What does need to be done,
848          * though, is all the housekeeping that is associated with non-linear
849          * changes in the value of _transport_frame. 
850          */
851          
852         if (actively_recording() && !for_seamless_loop) {
853                 return;
854         }
855
856         if (!force && _transport_frame == target_frame && !loop_changing && !for_seamless_loop) {
857                 if (with_roll) {
858                         set_transport_speed (1.0, false);
859                 }
860                 loop_changing = false;
861                 Located (); /* EMIT SIGNAL */
862                 return;
863         }
864
865         if (_transport_speed && !for_seamless_loop) {
866                 /* Schedule a declick.  We'll be called again when its done.
867                    We only do it this way for ordinary locates, not those
868                    due to **seamless** loops.
869                 */
870
871                 if (!(transport_sub_state & PendingDeclickOut)) {
872                         transport_sub_state |= (PendingDeclickOut|PendingLocate);
873                         pending_locate_frame = target_frame;
874                         pending_locate_roll = with_roll;
875                         pending_locate_flush = with_flush;
876                         return;
877                 }
878         }
879
880         // Update Timecode time
881         // [DR] FIXME: find out exactly where this should go below
882         _transport_frame = target_frame;
883         _last_roll_or_reversal_location = target_frame;
884         timecode_time(_transport_frame, transmitting_timecode_time);
885         outbound_mtc_timecode_frame = _transport_frame;
886         next_quarter_frame_to_send = 0;
887
888         /* do "stopped" stuff if:
889          *
890          * we are rolling AND
891          *    no autoplay in effect AND
892          *       we're not going to keep rolling after the locate AND
893          *           !(playing a loop with JACK sync)
894          *
895          */
896
897         bool transport_was_stopped = !transport_rolling();
898
899         if (transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
900                 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
901                 transport_was_stopped = true;
902         } else {
903                 /* otherwise tell the world that we located */
904                 realtime_locate ();
905         }
906
907         if (force || !for_seamless_loop || loop_changing) {
908
909                 PostTransportWork todo = PostTransportLocate;
910
911                 if (with_roll && transport_was_stopped) {
912                         todo = PostTransportWork (todo | PostTransportRoll);
913                 }
914
915                 add_post_transport_work (todo);
916                 _butler->schedule_transport_work ();
917
918         } else {
919
920                 /* this is functionally what clear_clicks() does but with a tentative lock */
921
922                 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
923
924                 if (clickm.locked()) {
925
926                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
927                                 delete *i;
928                         }
929
930                         clicks.clear ();
931                 }
932         }
933
934         if (with_roll) {
935                 /* switch from input if we're going to roll */
936                 if (Config->get_monitoring_model() == HardwareMonitoring) {
937                         set_track_monitor_input_status (!config.get_auto_input());
938                 }
939         } else {
940                 /* otherwise we're going to stop, so do the opposite */
941                 if (Config->get_monitoring_model() == HardwareMonitoring) {
942                         set_track_monitor_input_status (true);
943                 }
944         }
945
946         /* cancel looped playback if transport pos outside of loop range */
947         if (play_loop) {
948
949                 Location* al = _locations->auto_loop_location();
950
951                 if (al) {
952                         if (_transport_frame < al->start() || _transport_frame > al->end()) {
953
954                                 // located outside the loop: cancel looping directly, this is called from event handling context
955
956                                 set_play_loop (false);
957                                 
958                         } else if (_transport_frame == al->start()) {
959
960                                 // located to start of loop - this is looping, basically
961
962                                 if (for_seamless_loop) {
963
964                                         // this is only necessary for seamless looping
965                                         
966                                         boost::shared_ptr<RouteList> rl = routes.reader();
967
968                                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
969                                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
970
971                                                 if (tr && tr->record_enabled ()) {
972                                                         // tell it we've looped, so it can deal with the record state
973                                                         tr->transport_looped (_transport_frame);
974                                                 }
975                                         }
976                                 }
977
978                                 have_looped = true;
979                                 TransportLooped(); // EMIT SIGNAL
980                         }
981                 }
982         }
983
984         loop_changing = false;
985
986         _send_timecode_update = true;
987
988         if (with_mmc) {
989                 send_mmc_locate (_transport_frame);
990         }
991
992         Located (); /* EMIT SIGNAL */
993 }
994
995 /** Set the transport speed.
996  *  Called from the process thread.
997  *  @param speed New speed
998  */
999 void
1000 Session::set_transport_speed (double speed, bool abort, bool clear_state, bool as_default)
1001 {
1002         DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %5\n", 
1003                                                        speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1004
1005         if (_transport_speed == speed) {
1006                 return;
1007         }
1008
1009         if (actively_recording() && speed != 1.0 && speed != 0.0) {
1010                 /* no varispeed during recording */
1011                 return;
1012         }
1013
1014         _target_transport_speed = fabs(speed);
1015
1016         /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1017            and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1018         */
1019
1020         if (speed > 0) {
1021                 speed = min (8.0, speed);
1022         } else if (speed < 0) {
1023                 speed = max (-8.0, speed);
1024         }
1025
1026         if (transport_rolling() && speed == 0.0) {
1027
1028                 /* we are rolling and we want to stop */
1029
1030                 if (Config->get_monitoring_model() == HardwareMonitoring) {
1031                         set_track_monitor_input_status (true);
1032                 }
1033
1034                 if (synced_to_jack ()) {
1035                         if (clear_state) {
1036                                 /* do this here because our response to the slave won't
1037                                    take care of it.
1038                                 */
1039                                 _play_range = false;
1040                                 unset_play_loop ();
1041                         }
1042                         _engine.transport_stop ();
1043                 } else {
1044                         stop_transport (abort);
1045                 }
1046
1047                 unset_play_loop ();
1048
1049         } else if (transport_stopped() && speed == 1.0) {
1050
1051                 /* we are stopped and we want to start rolling at speed 1 */
1052
1053                 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1054                         set_track_monitor_input_status (false);
1055                 }
1056
1057                 if (synced_to_jack()) {
1058                         _engine.transport_start ();
1059                 } else {
1060                         start_transport ();
1061                 }
1062
1063         } else {
1064
1065                 /* not zero, not 1.0 ... varispeed */
1066
1067                 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
1068                         warning << string_compose (
1069                                 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1070                                 PROGRAM_NAME)
1071                                 << endmsg;
1072                         return;
1073                 }
1074
1075                 if (actively_recording()) {
1076                         return;
1077                 }
1078
1079                 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1080                         return;
1081                 }
1082
1083                 if (speed < 0.0 && _transport_frame == 0) {
1084                         return;
1085                 }
1086
1087                 clear_clicks ();
1088
1089                 /* if we are reversing relative to the current speed, or relative to the speed
1090                    before the last stop, then we have to do extra work.
1091                 */
1092
1093                 PostTransportWork todo = PostTransportWork (0);
1094
1095                 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1096                         todo = PostTransportWork (todo | PostTransportReverse);
1097                         _last_roll_or_reversal_location = _transport_frame;
1098                 }
1099
1100                 _last_transport_speed = _transport_speed;
1101                 _transport_speed = speed;
1102
1103                 if (as_default) {
1104                         _default_transport_speed = speed;
1105                 }
1106
1107                 boost::shared_ptr<RouteList> rl = routes.reader();
1108                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1109                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1110                         if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1111                                 todo = PostTransportWork (todo | PostTransportSpeed);
1112                         }
1113                 }
1114
1115                 if (todo) {
1116                         add_post_transport_work (todo);
1117                         _butler->schedule_transport_work ();
1118                 }
1119
1120                 TransportStateChange (); /* EMIT SIGNAL */
1121         }
1122 }
1123
1124
1125 /** Stop the transport.  */
1126 void
1127 Session::stop_transport (bool abort, bool clear_state)
1128 {
1129         if (_transport_speed == 0.0f) {
1130                 return;
1131         }
1132
1133         if (actively_recording() && !(transport_sub_state & StopPendingCapture) && worst_input_latency() > current_block_size) {
1134
1135                 boost::shared_ptr<RouteList> rl = routes.reader();
1136                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1137                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1138                         if (tr) {
1139                                 tr->prepare_to_stop (_transport_frame);
1140                         }
1141                 }
1142
1143                 /* we need to capture the audio that has still not yet been received by the system
1144                    at the time the stop is requested, so we have to roll past that time.
1145
1146                    we want to declick before stopping, so schedule the autostop for one
1147                    block before the actual end. we'll declick in the subsequent block,
1148                    and then we'll really be stopped.
1149                 */
1150
1151                 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 - %3 = %4, abort = %5\n",
1152                                                                _transport_frame, _worst_input_latency, current_block_size,
1153                                                                _transport_frame - _worst_input_latency - current_block_size,
1154                                                                abort));
1155
1156                 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1157                                                      _transport_frame + _worst_input_latency - current_block_size,
1158                                                      0, 0, abort);
1159
1160                 merge_event (ev);
1161                 transport_sub_state |= StopPendingCapture;
1162                 pending_abort = abort;
1163                 return;
1164         }
1165
1166         if ((transport_sub_state & PendingDeclickOut) == 0) {
1167
1168                 if (!(transport_sub_state & StopPendingCapture)) {
1169                         boost::shared_ptr<RouteList> rl = routes.reader();
1170                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1171                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1172                                 if (tr) {
1173                                         tr->prepare_to_stop (_transport_frame);
1174                                 }
1175                         }
1176                 }
1177
1178                 transport_sub_state |= PendingDeclickOut;
1179                 /* we'll be called again after the declick */
1180                 pending_abort = abort;
1181                 return;
1182         }
1183
1184         realtime_stop (abort, clear_state);
1185         _butler->schedule_transport_work ();
1186 }
1187
1188 /** Called from the process thread */
1189 void
1190 Session::start_transport ()
1191 {
1192         DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1193
1194         _last_roll_location = _transport_frame;
1195         _last_roll_or_reversal_location = _transport_frame;
1196
1197         have_looped = false;
1198
1199         /* if record status is Enabled, move it to Recording. if its
1200            already Recording, move it to Disabled.
1201         */
1202
1203         switch (record_status()) {
1204         case Enabled:
1205                 if (!config.get_punch_in()) {
1206                         enable_record ();
1207                 }
1208                 break;
1209
1210         case Recording:
1211                 if (!play_loop) {
1212                         disable_record (false);
1213                 }
1214                 break;
1215
1216         default:
1217                 break;
1218         }
1219
1220         transport_sub_state |= PendingDeclickIn;
1221
1222         _transport_speed = _default_transport_speed;
1223         _target_transport_speed = _transport_speed;
1224
1225         boost::shared_ptr<RouteList> rl = routes.reader();
1226         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1227                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1228                 if (tr) {
1229                         tr->realtime_set_speed (tr->speed(), true);
1230                 }
1231                 (*i)->automation_snapshot (_transport_frame, true);
1232         }
1233
1234         if (!_engine.freewheeling()) {
1235                 Timecode::Time time;
1236                 timecode_time_subframes (_transport_frame, time);
1237                 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1238                         MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1239                 }
1240         }
1241
1242         TransportStateChange (); /* EMIT SIGNAL */
1243 }
1244
1245 /** Do any transport work in the audio thread that needs to be done after the
1246  * transport thread is finished.  Audio thread, realtime safe.
1247  */
1248 void
1249 Session::post_transport ()
1250 {
1251         PostTransportWork ptw = post_transport_work ();
1252
1253         if (ptw & PostTransportAudition) {
1254                 if (auditioner && auditioner->auditioning()) {
1255                         process_function = &Session::process_audition;
1256                 } else {
1257                         process_function = &Session::process_with_events;
1258                 }
1259         }
1260
1261         if (ptw & PostTransportStop) {
1262
1263                 transport_sub_state = 0;
1264         }
1265
1266         if (ptw & PostTransportLocate) {
1267
1268                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1269                         start_transport ();
1270                 } else {
1271                         transport_sub_state = 0;
1272                 }
1273         }
1274
1275         set_next_event ();
1276         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1277            know were handled ?
1278         */
1279         set_post_transport_work (PostTransportWork (0));
1280 }
1281
1282 void
1283 Session::reset_rf_scale (framecnt_t motion)
1284 {
1285         cumulative_rf_motion += motion;
1286
1287         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1288                 rf_scale = 1;
1289         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1290                 rf_scale = 4;
1291         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1292                 rf_scale = 10;
1293         } else {
1294                 rf_scale = 100;
1295         }
1296
1297         if (motion != 0) {
1298                 set_dirty();
1299         }
1300 }
1301
1302 void
1303 Session::use_sync_source (Slave* new_slave)
1304 {
1305         /* Runs in process() context */
1306
1307         bool non_rt_required = false;
1308
1309         /* XXX this deletion is problematic because we're in RT context */
1310
1311         delete _slave;
1312         _slave = new_slave;
1313
1314         send_full_time_code (_transport_frame);
1315
1316         boost::shared_ptr<RouteList> rl = routes.reader();
1317         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1318                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1319                 if (tr && !tr->hidden()) {
1320                         if (tr->realtime_set_speed (tr->speed(), true)) {
1321                                 non_rt_required = true;
1322                         }
1323                         tr->set_slaved (_slave != 0);
1324                 }
1325         }
1326
1327         if (non_rt_required) {
1328                 add_post_transport_work (PostTransportSpeed);
1329                 _butler->schedule_transport_work ();
1330         }
1331
1332         set_dirty();
1333 }
1334
1335 void
1336 Session::drop_sync_source ()
1337 {
1338         request_sync_source (0);
1339 }
1340
1341 void
1342 Session::switch_to_sync_source (SyncSource src)
1343 {
1344         Slave* new_slave;
1345
1346         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1347
1348         switch (src) {
1349         case MTC:
1350                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1351                         return;
1352                 }
1353
1354                 try {
1355                         new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
1356                 }
1357
1358                 catch (failed_constructor& err) {
1359                         return;
1360                 }
1361                 break;
1362
1363         case MIDIClock:
1364                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1365                         return;
1366                 }
1367
1368                 try {
1369                         new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
1370                 }
1371
1372                 catch (failed_constructor& err) {
1373                         return;
1374                 }
1375                 break;
1376
1377         case JACK:
1378                 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1379                         return;
1380                 }
1381
1382                 if (config.get_video_pullup() != 0.0f) {
1383                         return;
1384                 }
1385
1386                 new_slave = new JACK_Slave (_engine.jack());
1387                 break;
1388
1389         default:
1390                 new_slave = 0;
1391                 break;
1392         };
1393
1394         request_sync_source (new_slave);
1395 }
1396
1397 void
1398 Session::set_track_speed (Track* track, double speed)
1399 {
1400         if (track->realtime_set_speed (speed, false)) {
1401                 add_post_transport_work (PostTransportSpeed);
1402                 _butler->schedule_transport_work ();
1403                 set_dirty ();
1404         }
1405 }
1406
1407 void
1408 Session::unset_play_range ()
1409 {
1410         _play_range = false;
1411         _clear_event_type (SessionEvent::RangeStop);
1412         _clear_event_type (SessionEvent::RangeLocate);
1413 }
1414
1415 void
1416 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1417 {
1418         SessionEvent* ev;
1419
1420         /* Called from event-processing context */
1421
1422         unset_play_range ();
1423
1424         if (range.empty()) {
1425                 /* _play_range set to false in unset_play_range()
1426                  */
1427                 if (!leave_rolling) {
1428                         /* stop transport */
1429                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1430                         merge_event (ev);
1431                 }
1432                 return;
1433         }
1434
1435         _play_range = true;
1436
1437         /* cancel loop play */
1438         unset_play_loop ();
1439
1440         list<AudioRange>::size_type sz = range.size();
1441
1442         if (sz > 1) {
1443
1444                 list<AudioRange>::iterator i = range.begin();
1445                 list<AudioRange>::iterator next;
1446
1447                 while (i != range.end()) {
1448
1449                         next = i;
1450                         ++next;
1451
1452                         /* locating/stopping is subject to delays for declicking.
1453                          */
1454
1455                         framepos_t requested_frame = i->end;
1456
1457                         if (requested_frame > current_block_size) {
1458                                 requested_frame -= current_block_size;
1459                         } else {
1460                                 requested_frame = 0;
1461                         }
1462
1463                         if (next == range.end()) {
1464                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1465                         } else {
1466                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1467                         }
1468
1469                         merge_event (ev);
1470
1471                         i = next;
1472                 }
1473
1474         } else if (sz == 1) {
1475
1476                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1477                 merge_event (ev);
1478
1479         }
1480
1481         /* save range so we can do auto-return etc. */
1482
1483         current_audio_range = range;
1484
1485         /* now start rolling at the right place */
1486
1487         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1488         merge_event (ev);
1489
1490         TransportStateChange ();
1491 }
1492
1493 void
1494 Session::request_bounded_roll (framepos_t start, framepos_t end)
1495 {
1496         AudioRange ar (start, end, 0);
1497         list<AudioRange> lar;
1498
1499         lar.push_back (ar);
1500         request_play_range (&lar, true);
1501 }
1502 void
1503 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1504 {
1505         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1506         ev->target2_frame = start;
1507         queue_event (ev);
1508 }
1509
1510 void
1511 Session::engine_halted ()
1512 {
1513         bool ignored;
1514
1515         /* there will be no more calls to process(), so
1516            we'd better clean up for ourselves, right now.
1517
1518            but first, make sure the butler is out of
1519            the picture.
1520         */
1521
1522         if (_butler) {
1523                 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1524                 set_post_transport_work (PostTransportWork (0));
1525                 _butler->stop ();
1526         }
1527
1528         realtime_stop (false, true);
1529         non_realtime_stop (false, 0, ignored);
1530         transport_sub_state = 0;
1531
1532         TransportStateChange (); /* EMIT SIGNAL */
1533 }
1534
1535
1536 void
1537 Session::xrun_recovery ()
1538 {
1539         Xrun (_transport_frame); /* EMIT SIGNAL */
1540
1541         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1542
1543                 /* it didn't actually halt, but we need
1544                    to handle things in the same way.
1545                 */
1546
1547                 engine_halted();
1548         }
1549 }
1550
1551 void
1552 Session::route_processors_changed (RouteProcessorChange c)
1553 {
1554         if (ignore_route_processor_changes) {
1555                 return;
1556         }
1557
1558         if (c.type == RouteProcessorChange::MeterPointChange) {
1559                 return;
1560         }
1561
1562         update_latency_compensation ();
1563         resort_routes ();
1564
1565         set_dirty ();
1566 }
1567
1568 void
1569 Session::allow_auto_play (bool yn)
1570 {
1571         auto_play_legal = yn;
1572 }
1573
1574 void
1575 Session::reset_jack_connection (jack_client_t* jack)
1576 {
1577         JACK_Slave* js;
1578
1579         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1580                 js->reset_client (jack);
1581         }
1582 }
1583
1584 bool
1585 Session::maybe_stop (framepos_t limit)
1586 {
1587         if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1588                 if (synced_to_jack () && config.get_jack_time_master ()) {
1589                         _engine.transport_stop ();
1590                 } else if (!synced_to_jack ()) {
1591                         stop_transport ();
1592                 }
1593                 return true;
1594         }
1595         return false;
1596 }
1597
1598 void
1599 Session::send_mmc_locate (framepos_t t)
1600 {
1601         if (!_engine.freewheeling()) {
1602                 Timecode::Time time;
1603                 timecode_time_subframes (t, time);
1604                 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
1605         }
1606 }
1607
1608 /** Ask the transport to not send timecode until further notice.  The suspension
1609  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
1610  *  should be checked by the caller to find out when.
1611  */
1612 void
1613 Session::request_suspend_timecode_transmission ()
1614 {
1615         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1616         queue_event (ev);
1617 }
1618
1619 void
1620 Session::request_resume_timecode_transmission ()
1621 {
1622         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1623         queue_event (ev);
1624 }
1625
1626 bool
1627 Session::timecode_transmission_suspended () const
1628 {
1629         return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
1630 }