Fix up my previous buggy MMC cleanup.
[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                 return;
787         }
788
789         // Update Timecode time
790         // [DR] FIXME: find out exactly where this should go below
791         _transport_frame = target_frame;
792         timecode_time(_transport_frame, transmitting_timecode_time);
793         outbound_mtc_timecode_frame = _transport_frame;
794         next_quarter_frame_to_send = 0;
795
796         if (_transport_speed && (!with_loop || loop_changing)) {
797                 /* schedule a declick. we'll be called again when its done */
798
799                 if (!(transport_sub_state & PendingDeclickOut)) {
800                         transport_sub_state |= (PendingDeclickOut|PendingLocate);
801                         pending_locate_frame = target_frame;
802                         pending_locate_roll = with_roll;
803                         pending_locate_flush = with_flush;
804                         return;
805                 }
806         }
807
808         if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
809                 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
810         }
811
812         if (force || !with_loop || loop_changing) {
813
814                 PostTransportWork todo = PostTransportLocate;
815
816                 if (with_roll) {
817                         todo = PostTransportWork (todo | PostTransportRoll);
818                 } 
819
820                 add_post_transport_work (todo);
821                 _butler->schedule_transport_work ();
822
823         } else {
824
825                 /* this is functionally what clear_clicks() does but with a tentative lock */
826
827                 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
828
829                 if (clickm.locked()) {
830
831                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
832                                 delete *i;
833                         }
834
835                         clicks.clear ();
836                 }
837         }
838
839         if (with_roll) {
840                 /* switch from input if we're going to roll */
841                 if (Config->get_monitoring_model() == HardwareMonitoring) {
842
843                         boost::shared_ptr<RouteList> rl = routes.reader();
844                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
845                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
846                                 if (tr && tr->record_enabled ()) {
847                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
848                                         tr->monitor_input (!config.get_auto_input());
849                                 }
850                         }
851                 }
852         } else {
853                 /* otherwise we're going to stop, so do the opposite */
854                 if (Config->get_monitoring_model() == HardwareMonitoring) {
855
856                         boost::shared_ptr<RouteList> rl = routes.reader();
857                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
858                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
859                                 if (tr && tr->record_enabled ()) {
860                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
861                                         tr->monitor_input (true);
862                                 }
863                         }
864                 }
865         }
866
867         /* cancel looped playback if transport pos outside of loop range */
868         if (play_loop) {
869                 Location* al = _locations.auto_loop_location();
870
871                 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
872                         // cancel looping directly, this is called from event handling context
873                         set_play_loop (false);
874                 }
875                 else if (al && _transport_frame == al->start()) {
876                         if (with_loop) {
877                                 // this is only necessary for seamless looping
878
879                                 boost::shared_ptr<RouteList> rl = routes.reader();
880                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
881                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
882                                         if (tr && tr->record_enabled ()) {
883                                                 // tell it we've looped, so it can deal with the record state
884                                                 tr->transport_looped(_transport_frame);
885                                         }
886                                 }
887                         }
888                         have_looped = true;
889                         TransportLooped(); // EMIT SIGNAL
890                 }
891         }
892
893         loop_changing = false;
894
895         _send_timecode_update = true;
896
897         if (with_mmc) {
898                 Timecode::Time time;
899                 timecode_time_subframes (_transport_frame, time);
900                 _mmc->send (MIDI::MachineControlCommand (time));
901         }
902
903         Located (); /* EMIT SIGNAL */
904 }
905
906 /** Set the transport speed.
907  * @param speed New speed
908  * @param abort
909  */
910 void
911 Session::set_transport_speed (double speed, bool abort, bool clear_state)
912 {
913         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));
914
915         if (_transport_speed == speed) {
916                 return;
917         }
918
919         _target_transport_speed = fabs(speed);
920
921         /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
922            and user needs. We really need CD-style "skip" playback for ffwd and rewind.
923         */
924
925         if (speed > 0) {
926                 speed = min (8.0, speed);
927         } else if (speed < 0) {
928                 speed = max (-8.0, speed);
929         }
930
931         if (transport_rolling() && speed == 0.0) {
932
933                 /* we are rolling and we want to stop */
934
935                 if (Config->get_monitoring_model() == HardwareMonitoring)
936                 {
937                         boost::shared_ptr<RouteList> rl = routes.reader();
938                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
939                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
940                                 if (tr && tr->record_enabled ()) {
941                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
942                                         tr->monitor_input (true);
943                                 }
944                         }
945                 }
946
947                 if (synced_to_jack ()) {
948                         if (clear_state) {
949                                 /* do this here because our response to the slave won't 
950                                    take care of it.
951                                 */
952                                 _play_range = false;
953                                 unset_play_loop ();
954                         }
955                         _engine.transport_stop ();
956                 } else {
957                         stop_transport (abort);
958                 }
959
960         } else if (transport_stopped() && speed == 1.0) {
961
962                 /* we are stopped and we want to start rolling at speed 1 */
963
964                 if (Config->get_monitoring_model() == HardwareMonitoring) {
965
966                         boost::shared_ptr<RouteList> rl = routes.reader();
967                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
968                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
969                                 if (config.get_auto_input() && tr && tr->record_enabled ()) {
970                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
971                                         tr->monitor_input (false);
972                                 }
973                         }
974                 }
975
976                 if (synced_to_jack()) {
977                         _engine.transport_start ();
978                 } else {
979                         start_transport ();
980                 }
981
982         } else {
983
984                 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
985                         warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
986                                                    PROGRAM_NAME)
987                                 << endmsg;
988                         return;
989                 }
990
991                 if (actively_recording()) {
992                         return;
993                 }
994
995                 if (speed > 0.0 && _transport_frame == current_end_frame()) {
996                         return;
997                 }
998
999                 if (speed < 0.0 && _transport_frame == 0) {
1000                         return;
1001                 }
1002
1003                 clear_clicks ();
1004
1005                 /* if we are reversing relative to the current speed, or relative to the speed
1006                    before the last stop, then we have to do extra work.
1007                 */
1008                 
1009                 PostTransportWork todo = PostTransportWork (0);
1010
1011                 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1012                         todo = PostTransportWork (todo | PostTransportReverse);
1013                         _last_roll_or_reversal_location = _transport_frame;
1014                 }
1015
1016                 _last_transport_speed = _transport_speed;
1017                 _transport_speed = speed;
1018
1019                 boost::shared_ptr<RouteList> rl = routes.reader();
1020                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1021                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1022                         if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1023                                 todo = PostTransportWork (todo | PostTransportSpeed);
1024                                 break;
1025                         }
1026                 }
1027
1028                 if (todo) {
1029                         add_post_transport_work (todo);
1030                         _butler->schedule_transport_work ();
1031                 }
1032         }
1033 }
1034
1035
1036 /** Stop the transport.  */
1037 void
1038 Session::stop_transport (bool abort, bool clear_state)
1039 {
1040         if (_transport_speed == 0.0f) {
1041                 return;
1042         }
1043
1044         if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1045
1046                 boost::shared_ptr<RouteList> rl = routes.reader();
1047                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1048                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1049                         if (tr) {
1050                                 tr->prepare_to_stop (_transport_frame);
1051                         }
1052                 }
1053
1054                 /* we need to capture the audio that has still not yet been received by the system
1055                    at the time the stop is requested, so we have to roll past that time.
1056
1057                    we want to declick before stopping, so schedule the autostop for one
1058                    block before the actual end. we'll declick in the subsequent block,
1059                    and then we'll really be stopped.
1060                 */
1061
1062                 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1063                                        _transport_frame + _worst_output_latency - current_block_size,
1064                                        0, 0, abort);
1065
1066                 merge_event (ev);
1067                 transport_sub_state |= StopPendingCapture;
1068                 pending_abort = abort;
1069                 return;
1070         }
1071
1072
1073         if ((transport_sub_state & PendingDeclickOut) == 0) {
1074
1075                 if (!(transport_sub_state & StopPendingCapture)) {
1076                         boost::shared_ptr<RouteList> rl = routes.reader();
1077                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1078                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1079                                 if (tr) {
1080                                         tr->prepare_to_stop (_transport_frame);
1081                                 }
1082                         }
1083                 }
1084                 
1085                 transport_sub_state |= PendingDeclickOut;
1086                 /* we'll be called again after the declick */
1087                 pending_abort = abort;
1088                 return;
1089         }
1090
1091         realtime_stop (abort, clear_state);
1092         _butler->schedule_transport_work ();
1093 }
1094
1095 void
1096 Session::start_transport ()
1097 {
1098         _last_roll_location = _transport_frame;
1099         _last_roll_or_reversal_location = _transport_frame;
1100         
1101         have_looped = false;
1102
1103         /* if record status is Enabled, move it to Recording. if its
1104            already Recording, move it to Disabled.
1105         */
1106
1107         switch (record_status()) {
1108         case Enabled:
1109                 if (!config.get_punch_in()) {
1110                         enable_record ();
1111                 }
1112                 break;
1113
1114         case Recording:
1115                 if (!play_loop) {
1116                         disable_record (false);
1117                 }
1118                 break;
1119
1120         default:
1121                 break;
1122         }
1123
1124         transport_sub_state |= PendingDeclickIn;
1125
1126         _transport_speed = 1.0;
1127         _target_transport_speed = 1.0;
1128
1129         boost::shared_ptr<RouteList> rl = routes.reader();
1130         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1131                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1132                 if (tr) {
1133                         tr->realtime_set_speed (tr->speed(), true);
1134                 }
1135         }
1136
1137         Timecode::Time time;
1138         timecode_time_subframes (_transport_frame, time);
1139         _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1140
1141         TransportStateChange (); /* EMIT SIGNAL */
1142 }
1143
1144 /** Do any transport work in the audio thread that needs to be done after the
1145  * transport thread is finished.  Audio thread, realtime safe.
1146  */
1147 void
1148 Session::post_transport ()
1149 {
1150         PostTransportWork ptw = post_transport_work ();
1151
1152         if (ptw & PostTransportAudition) {
1153                 if (auditioner && auditioner->auditioning()) {
1154                         process_function = &Session::process_audition;
1155                 } else {
1156                         process_function = &Session::process_with_events;
1157                 }
1158         }
1159
1160         if (ptw & PostTransportStop) {
1161
1162                 transport_sub_state = 0;
1163         }
1164
1165         if (ptw & PostTransportLocate) {
1166
1167                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1168                         start_transport ();
1169
1170                 } else {
1171                         transport_sub_state = 0;
1172                 }
1173         }
1174
1175         set_next_event ();
1176         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1177            know were handled ?
1178         */
1179         set_post_transport_work (PostTransportWork (0));
1180 }
1181
1182 void
1183 Session::reset_rf_scale (nframes_t motion)
1184 {
1185         cumulative_rf_motion += motion;
1186
1187         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1188                 rf_scale = 1;
1189         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1190                 rf_scale = 4;
1191         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1192                 rf_scale = 10;
1193         } else {
1194                 rf_scale = 100;
1195         }
1196
1197         if (motion != 0) {
1198                 set_dirty();
1199         }
1200 }
1201
1202 void
1203 Session::use_sync_source (Slave* new_slave)
1204 {
1205         /* Runs in process() context */
1206
1207         bool non_rt_required = false;
1208
1209         /* XXX this deletion is problematic because we're in RT context */
1210
1211         delete _slave;
1212         _slave = new_slave;
1213
1214         boost::shared_ptr<RouteList> rl = routes.reader();
1215         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1216                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1217                 if (tr && !tr->hidden()) {
1218                         if (tr->realtime_set_speed (tr->speed(), true)) {
1219                                 non_rt_required = true;
1220                         }
1221                         tr->set_slaved (_slave != 0);
1222                 }
1223         }
1224
1225         if (non_rt_required) {
1226                 add_post_transport_work (PostTransportSpeed);
1227                 _butler->schedule_transport_work ();
1228         }
1229
1230         set_dirty();
1231 }
1232
1233 void
1234 Session::drop_sync_source ()
1235 {
1236         request_sync_source (0);
1237 }
1238
1239 void
1240 Session::switch_to_sync_source (SyncSource src)
1241 {
1242         Slave* new_slave;
1243
1244         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1245
1246         switch (src) {
1247         case MTC:
1248                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1249                         return;
1250                 }
1251
1252                 if (_mtc_port) {
1253                         try {
1254                                 new_slave = new MTC_Slave (*this, *_mtc_port);
1255                         }
1256
1257                         catch (failed_constructor& err) {
1258                                 return;
1259                         }
1260
1261                 } else {
1262                         error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1263                         return;
1264                 }
1265                 break;
1266
1267         case MIDIClock:
1268                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1269                         return;
1270                 }
1271
1272                 if (_midi_clock_port) {
1273                         try {
1274                                 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1275                         }
1276
1277                         catch (failed_constructor& err) {
1278                                 return;
1279                         }
1280
1281                 } else {
1282                         error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1283                         return;
1284                 }
1285                 break;
1286
1287         case JACK:
1288                 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1289                         return;
1290                 }
1291
1292                 new_slave = new JACK_Slave (_engine.jack());
1293                 break;
1294                 
1295         default:
1296                 new_slave = 0;
1297                 break;
1298         };
1299
1300         request_sync_source (new_slave);
1301 }
1302
1303 void
1304 Session::reverse_track_buffers ()
1305 {
1306         add_post_transport_work (PostTransportReverse);
1307         _butler->schedule_transport_work ();
1308 }
1309
1310 void
1311 Session::set_track_speed (Track* track, double speed)
1312 {
1313         if (track->realtime_set_speed (speed, false)) {
1314                 add_post_transport_work (PostTransportSpeed);
1315                 _butler->schedule_transport_work ();
1316                 set_dirty ();
1317         }
1318 }
1319
1320 void
1321 Session::unset_play_range ()
1322 {
1323         _play_range = false;
1324         _clear_event_type (SessionEvent::RangeStop);
1325         _clear_event_type (SessionEvent::RangeLocate);
1326 }
1327
1328 void
1329 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1330 {
1331         SessionEvent* ev;
1332
1333         /* Called from event-processing context */
1334
1335         unset_play_range ();
1336         
1337         if (range.empty()) {
1338                 /* _play_range set to false in unset_play_range()
1339                  */
1340                 if (!leave_rolling) {
1341                         /* stop transport */
1342                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1343                         merge_event (ev);
1344                 }
1345                 return;
1346         }
1347
1348         _play_range = true;
1349
1350         /* cancel loop play */
1351         unset_play_loop ();
1352
1353         list<AudioRange>::size_type sz = range.size();
1354         
1355         if (sz > 1) {
1356                 
1357                 list<AudioRange>::iterator i = range.begin(); 
1358                 list<AudioRange>::iterator next;
1359                 
1360                 while (i != range.end()) {
1361                         
1362                         next = i;
1363                         ++next;
1364                         
1365                         /* locating/stopping is subject to delays for declicking.
1366                          */
1367                         
1368                         nframes_t requested_frame = (*i).end;
1369                         
1370                         if (requested_frame > current_block_size) {
1371                                 requested_frame -= current_block_size;
1372                         } else {
1373                                 requested_frame = 0;
1374                         }
1375                         
1376                         if (next == range.end()) {
1377                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1378                         } else {
1379                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1380                         }
1381                         
1382                         merge_event (ev);
1383                         
1384                         i = next;
1385                 }
1386                 
1387         } else if (sz == 1) {
1388
1389                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1390                 merge_event (ev);
1391                 
1392         } 
1393
1394         /* save range so we can do auto-return etc. */
1395
1396         current_audio_range = range;
1397
1398         /* now start rolling at the right place */
1399
1400         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1401         merge_event (ev);
1402         
1403         TransportStateChange ();
1404 }
1405
1406 void
1407 Session::request_bounded_roll (nframes_t start, nframes_t end)
1408 {
1409         AudioRange ar (start, end, 0);
1410         list<AudioRange> lar;
1411
1412         lar.push_back (ar);
1413         request_play_range (&lar, true);
1414 }
1415 void
1416 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1417 {
1418         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1419         ev->target2_frame = start;
1420         queue_event (ev);
1421 }
1422
1423 void
1424 Session::engine_halted ()
1425 {
1426         bool ignored;
1427
1428         /* there will be no more calls to process(), so
1429            we'd better clean up for ourselves, right now.
1430
1431            but first, make sure the butler is out of
1432            the picture.
1433         */
1434
1435         g_atomic_int_set (&_butler->should_do_transport_work, 0);
1436         set_post_transport_work (PostTransportWork (0));
1437         _butler->stop ();
1438
1439         realtime_stop (false, true);
1440         non_realtime_stop (false, 0, ignored);
1441         transport_sub_state = 0;
1442
1443         TransportStateChange (); /* EMIT SIGNAL */
1444 }
1445
1446
1447 void
1448 Session::xrun_recovery ()
1449 {
1450         // can't cast away volatile so copy and emit that
1451         nframes64_t tframe = _transport_frame;
1452         Xrun (tframe); //EMIT SIGNAL
1453
1454         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1455
1456                 /* it didn't actually halt, but we need
1457                    to handle things in the same way.
1458                 */
1459
1460                 engine_halted();
1461         }
1462 }
1463
1464 void
1465 Session::route_processors_changed (RouteProcessorChange c)
1466 {
1467         if (c.type == RouteProcessorChange::MeterPointChange) {
1468                 return;
1469         }
1470
1471         update_latency_compensation (false, false);
1472         resort_routes ();
1473 }
1474
1475 void
1476 Session::update_latency_compensation (bool with_stop, bool abort)
1477 {
1478         bool update_jack = false;
1479         PostTransportWork ptw;
1480
1481         if (_state_of_the_state & Deletion) {
1482                 return;
1483         }
1484
1485         _worst_track_latency = 0;
1486         ptw = post_transport_work();
1487
1488 #undef DEBUG_LATENCY
1489 #ifdef DEBUG_LATENCY
1490         cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1491 #endif
1492
1493         boost::shared_ptr<RouteList> r = routes.reader ();
1494
1495         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1496
1497                 if (with_stop) {
1498                         (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1499                 }
1500
1501                 nframes_t old_latency = (*i)->output()->signal_latency ();
1502                 nframes_t track_latency = (*i)->update_total_latency ();
1503
1504                 if (old_latency != track_latency) {
1505                         (*i)->input()->update_port_total_latencies ();
1506                         (*i)->output()->update_port_total_latencies ();
1507                         update_jack = true;
1508                 }
1509
1510                 if (!(*i)->is_hidden() && ((*i)->active())) {
1511                         _worst_track_latency = max (_worst_track_latency, track_latency);
1512                 }
1513         }
1514
1515         if (update_jack) {
1516                 _engine.update_total_latencies ();
1517         }
1518
1519 #ifdef DEBUG_LATENCY
1520         cerr << "\tworst was " << _worst_track_latency << endl;
1521 #endif
1522
1523         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1524                 (*i)->set_latency_delay (_worst_track_latency);
1525         }
1526
1527         set_worst_io_latencies ();
1528
1529         /* reflect any changes in latencies into capture offsets
1530         */
1531         
1532         boost::shared_ptr<RouteList> rl = routes.reader();
1533         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1534                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1535                 if (tr) {
1536                         tr->set_capture_offset ();
1537                 }
1538         }
1539 }
1540
1541 void
1542 Session::allow_auto_play (bool yn)
1543 {
1544         auto_play_legal = yn;
1545 }
1546
1547 void
1548 Session::reset_jack_connection (jack_client_t* jack)
1549 {
1550         JACK_Slave* js;
1551
1552         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1553                 js->reset_client (jack);
1554         }
1555 }
1556
1557 bool
1558 Session::maybe_stop (nframes_t limit)
1559 {
1560        if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1561                if (synced_to_jack () && config.get_jack_time_master ()) {
1562                        _engine.transport_stop ();
1563                } else if (!synced_to_jack ()) {
1564                        stop_transport ();
1565                }
1566                return true;
1567        }
1568        return false;
1569 }