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