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