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