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