add missing files
[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         TransportStateChange (); /* EMIT SIGNAL */
642
643         /* and start it up again if relevant */
644
645         if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
646                 request_transport_speed (1.0);
647                 pending_locate_roll = false;
648         }
649 }
650
651 void
652 Session::check_declick_out ()
653 {
654         bool locate_required = transport_sub_state & PendingLocate;
655
656         /* this is called after a process() iteration. if PendingDeclickOut was set,
657            it means that we were waiting to declick the output (which has just been
658            done) before maybe doing something else. this is where we do that "something else".
659
660            note: called from the audio thread.
661         */
662
663         if (transport_sub_state & PendingDeclickOut) {
664
665                 if (locate_required) {
666                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
667                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
668                 } else {
669                         stop_transport (pending_abort);
670                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
671                 }
672
673         } else if (transport_sub_state & PendingLoopDeclickOut) {
674                 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
675                 transport_sub_state &= ~PendingLoopDeclickOut;
676         }
677 }
678
679 void
680 Session::unset_play_loop ()
681 {
682         play_loop = false;
683         clear_events (SessionEvent::AutoLoop);
684         clear_events (SessionEvent::AutoLoopDeclick);
685
686         // set all tracks to NOT use internal looping
687         boost::shared_ptr<RouteList> rl = routes.reader ();
688         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
689                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
690                 if (tr && !tr->hidden()) {
691                         tr->set_loop (0);
692                 }
693         }
694 }
695
696 void
697 Session::set_play_loop (bool yn)
698 {
699         /* Called from event-handling context */
700
701         Location *loc;
702
703         if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
704                 /* nothing to do, or can't change loop status while recording */
705                 return;
706         }
707
708         if (yn && Config->get_seamless_loop() && synced_to_jack()) {
709                 warning << string_compose (
710                         _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
711                           "Recommend changing the configured options"), PROGRAM_NAME)
712                         << endmsg;
713                 return;
714         }
715
716         if (yn) {
717
718                 play_loop = true;
719
720                 if (loc) {
721
722                         unset_play_range ();
723
724                         if (Config->get_seamless_loop()) {
725                                 // set all tracks to use internal looping
726                                 boost::shared_ptr<RouteList> rl = routes.reader ();
727                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
728                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
729                                         if (tr && !tr->hidden()) {
730                                                 tr->set_loop (loc);
731                                         }
732                                 }
733                         }
734                         else {
735                                 // set all tracks to NOT use internal looping
736                                 boost::shared_ptr<RouteList> rl = routes.reader ();
737                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
738                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
739                                         if (tr && !tr->hidden()) {
740                                                 tr->set_loop (0);
741                                         }
742                                 }
743                         }
744
745                         /* Put the delick and loop events in into the event list.  The declick event will
746                            cause a de-clicking fade-out just before the end of the loop, and it will also result
747                            in a fade-in when the loop restarts.  The AutoLoop event will peform the actual loop.
748                         */
749
750                         framepos_t dcp;
751                         framecnt_t dcl;
752                         auto_loop_declick_range (loc, dcp, dcl);
753                         merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
754                         merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
755
756                         /* locate to start of loop and roll. 
757
758                            args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
759                         */
760
761                         start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
762                 }
763
764         } else {
765
766                 unset_play_loop ();
767         }
768
769         TransportStateChange ();
770 }
771 void
772 Session::flush_all_inserts ()
773 {
774         boost::shared_ptr<RouteList> r = routes.reader ();
775
776         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
777                 (*i)->flush_processors ();
778         }
779 }
780
781 void
782 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
783 {
784         if (synced_to_jack()) {
785
786                 double sp;
787                 framepos_t pos;
788
789                 _slave->speed_and_position (sp, pos);
790
791                 if (target_frame != pos) {
792
793                         if (config.get_jack_time_master()) {
794                                 /* actually locate now, since otherwise jack_timebase_callback
795                                    will use the incorrect _transport_frame and report an old
796                                    and incorrect time to Jack transport
797                                 */
798                                 locate (target_frame, with_roll, with_flush, with_loop, force);
799                         }
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         }
1232
1233         if (!_engine.freewheeling()) {
1234                 Timecode::Time time;
1235                 timecode_time_subframes (_transport_frame, time);
1236                 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1237                         MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1238                 }
1239         }
1240
1241         TransportStateChange (); /* EMIT SIGNAL */
1242 }
1243
1244 /** Do any transport work in the audio thread that needs to be done after the
1245  * transport thread is finished.  Audio thread, realtime safe.
1246  */
1247 void
1248 Session::post_transport ()
1249 {
1250         PostTransportWork ptw = post_transport_work ();
1251
1252         if (ptw & PostTransportAudition) {
1253                 if (auditioner && auditioner->auditioning()) {
1254                         process_function = &Session::process_audition;
1255                 } else {
1256                         process_function = &Session::process_with_events;
1257                 }
1258         }
1259
1260         if (ptw & PostTransportStop) {
1261
1262                 transport_sub_state = 0;
1263         }
1264
1265         if (ptw & PostTransportLocate) {
1266
1267                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1268                         start_transport ();
1269                 } else {
1270                         transport_sub_state = 0;
1271                 }
1272         }
1273
1274         set_next_event ();
1275         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1276            know were handled ?
1277         */
1278         set_post_transport_work (PostTransportWork (0));
1279 }
1280
1281 void
1282 Session::reset_rf_scale (framecnt_t motion)
1283 {
1284         cumulative_rf_motion += motion;
1285
1286         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1287                 rf_scale = 1;
1288         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1289                 rf_scale = 4;
1290         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1291                 rf_scale = 10;
1292         } else {
1293                 rf_scale = 100;
1294         }
1295
1296         if (motion != 0) {
1297                 set_dirty();
1298         }
1299 }
1300
1301 void
1302 Session::use_sync_source (Slave* new_slave)
1303 {
1304         /* Runs in process() context */
1305
1306         bool non_rt_required = false;
1307
1308         /* XXX this deletion is problematic because we're in RT context */
1309
1310         delete _slave;
1311         _slave = new_slave;
1312
1313         send_full_time_code (_transport_frame);
1314
1315         boost::shared_ptr<RouteList> rl = routes.reader();
1316         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1317                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1318                 if (tr && !tr->hidden()) {
1319                         if (tr->realtime_set_speed (tr->speed(), true)) {
1320                                 non_rt_required = true;
1321                         }
1322                         tr->set_slaved (_slave != 0);
1323                 }
1324         }
1325
1326         if (non_rt_required) {
1327                 add_post_transport_work (PostTransportSpeed);
1328                 _butler->schedule_transport_work ();
1329         }
1330
1331         set_dirty();
1332 }
1333
1334 void
1335 Session::drop_sync_source ()
1336 {
1337         request_sync_source (0);
1338 }
1339
1340 void
1341 Session::switch_to_sync_source (SyncSource src)
1342 {
1343         Slave* new_slave;
1344
1345         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1346
1347         switch (src) {
1348         case MTC:
1349                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1350                         return;
1351                 }
1352
1353                 try {
1354                         new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
1355                 }
1356
1357                 catch (failed_constructor& err) {
1358                         return;
1359                 }
1360                 break;
1361
1362         case MIDIClock:
1363                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1364                         return;
1365                 }
1366
1367                 try {
1368                         new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
1369                 }
1370
1371                 catch (failed_constructor& err) {
1372                         return;
1373                 }
1374                 break;
1375
1376         case JACK:
1377                 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1378                         return;
1379                 }
1380
1381                 if (config.get_video_pullup() != 0.0f) {
1382                         return;
1383                 }
1384
1385                 new_slave = new JACK_Slave (_engine.jack());
1386                 break;
1387
1388         default:
1389                 new_slave = 0;
1390                 break;
1391         };
1392
1393         request_sync_source (new_slave);
1394 }
1395
1396 void
1397 Session::set_track_speed (Track* track, double speed)
1398 {
1399         if (track->realtime_set_speed (speed, false)) {
1400                 add_post_transport_work (PostTransportSpeed);
1401                 _butler->schedule_transport_work ();
1402                 set_dirty ();
1403         }
1404 }
1405
1406 void
1407 Session::unset_play_range ()
1408 {
1409         _play_range = false;
1410         _clear_event_type (SessionEvent::RangeStop);
1411         _clear_event_type (SessionEvent::RangeLocate);
1412 }
1413
1414 void
1415 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1416 {
1417         SessionEvent* ev;
1418
1419         /* Called from event-processing context */
1420
1421         unset_play_range ();
1422
1423         if (range.empty()) {
1424                 /* _play_range set to false in unset_play_range()
1425                  */
1426                 if (!leave_rolling) {
1427                         /* stop transport */
1428                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1429                         merge_event (ev);
1430                 }
1431                 return;
1432         }
1433
1434         _play_range = true;
1435
1436         /* cancel loop play */
1437         unset_play_loop ();
1438
1439         list<AudioRange>::size_type sz = range.size();
1440
1441         if (sz > 1) {
1442
1443                 list<AudioRange>::iterator i = range.begin();
1444                 list<AudioRange>::iterator next;
1445
1446                 while (i != range.end()) {
1447
1448                         next = i;
1449                         ++next;
1450
1451                         /* locating/stopping is subject to delays for declicking.
1452                          */
1453
1454                         framepos_t requested_frame = i->end;
1455
1456                         if (requested_frame > current_block_size) {
1457                                 requested_frame -= current_block_size;
1458                         } else {
1459                                 requested_frame = 0;
1460                         }
1461
1462                         if (next == range.end()) {
1463                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1464                         } else {
1465                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1466                         }
1467
1468                         merge_event (ev);
1469
1470                         i = next;
1471                 }
1472
1473         } else if (sz == 1) {
1474
1475                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1476                 merge_event (ev);
1477
1478         }
1479
1480         /* save range so we can do auto-return etc. */
1481
1482         current_audio_range = range;
1483
1484         /* now start rolling at the right place */
1485
1486         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1487         merge_event (ev);
1488
1489         TransportStateChange ();
1490 }
1491
1492 void
1493 Session::request_bounded_roll (framepos_t start, framepos_t end)
1494 {
1495         AudioRange ar (start, end, 0);
1496         list<AudioRange> lar;
1497
1498         lar.push_back (ar);
1499         request_play_range (&lar, true);
1500 }
1501 void
1502 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1503 {
1504         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1505         ev->target2_frame = start;
1506         queue_event (ev);
1507 }
1508
1509 void
1510 Session::engine_halted ()
1511 {
1512         bool ignored;
1513
1514         /* there will be no more calls to process(), so
1515            we'd better clean up for ourselves, right now.
1516
1517            but first, make sure the butler is out of
1518            the picture.
1519         */
1520
1521         if (_butler) {
1522                 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1523                 set_post_transport_work (PostTransportWork (0));
1524                 _butler->stop ();
1525         }
1526
1527         realtime_stop (false, true);
1528         non_realtime_stop (false, 0, ignored);
1529         transport_sub_state = 0;
1530
1531         TransportStateChange (); /* EMIT SIGNAL */
1532 }
1533
1534
1535 void
1536 Session::xrun_recovery ()
1537 {
1538         Xrun (_transport_frame); /* EMIT SIGNAL */
1539
1540         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1541
1542                 /* it didn't actually halt, but we need
1543                    to handle things in the same way.
1544                 */
1545
1546                 engine_halted();
1547         }
1548 }
1549
1550 void
1551 Session::route_processors_changed (RouteProcessorChange c)
1552 {
1553         if (ignore_route_processor_changes) {
1554                 return;
1555         }
1556
1557         if (c.type == RouteProcessorChange::MeterPointChange) {
1558                 return;
1559         }
1560
1561         update_latency_compensation ();
1562         resort_routes ();
1563
1564         set_dirty ();
1565 }
1566
1567 void
1568 Session::allow_auto_play (bool yn)
1569 {
1570         auto_play_legal = yn;
1571 }
1572
1573 void
1574 Session::reset_jack_connection (jack_client_t* jack)
1575 {
1576         JACK_Slave* js;
1577
1578         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1579                 js->reset_client (jack);
1580         }
1581 }
1582
1583 bool
1584 Session::maybe_stop (framepos_t limit)
1585 {
1586         if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1587                 if (synced_to_jack () && config.get_jack_time_master ()) {
1588                         _engine.transport_stop ();
1589                 } else if (!synced_to_jack ()) {
1590                         stop_transport ();
1591                 }
1592                 return true;
1593         }
1594         return false;
1595 }
1596
1597 void
1598 Session::send_mmc_locate (framepos_t t)
1599 {
1600         if (!_engine.freewheeling()) {
1601                 Timecode::Time time;
1602                 timecode_time_subframes (t, time);
1603                 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
1604         }
1605 }
1606
1607 /** Ask the transport to not send timecode until further notice.  The suspension
1608  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
1609  *  should be checked by the caller to find out when.
1610  */
1611 void
1612 Session::request_suspend_timecode_transmission ()
1613 {
1614         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1615         queue_event (ev);
1616 }
1617
1618 void
1619 Session::request_resume_timecode_transmission ()
1620 {
1621         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1622         queue_event (ev);
1623 }
1624
1625 bool
1626 Session::timecode_transmission_suspended () const
1627 {
1628         return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
1629 }