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