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